加锁并发算法 vs 无锁并发算法
Heinz Kabutz 在上周举办了一次成功 JCrete研讨会,我在会上参加了对一种新的 StampedLock(于JSR166中 引入) 进行的评审。StampedLock (邮戳锁) 旨在解决系统中共享资源的争用问题。在一个系统中,如果多个需要读写某一共享状态的程序并发访问这个共享对象时,争用问题就产生了。在设计 上,StampedLock 试图通过一种“乐观读取”的方式来减小系统开销,从而提供比 ReentrantReadWriteLock(重入读写锁) 更好的性能。
在评审过程中,我产生了许多想法:首先,这是我第一次评审Java 中最新锁机制的实现。其次,尽管 StampedLock 看起来是一个对 JDK 不错的补充,但是它似乎忽略了一个事实——无锁算法通常在多读取程序访问共享资源时能提供更好的性能。
测试用例
为了比较不同的实现,我首先需要一个 API 调用作为测试用例。这个 API 调用不能在某些算法或条件下表现出特别的性质,比如这个调用不应产生垃圾对象,同时调用的方法可以具有原子性。据此我构造了一个简单的测试用例——构建一 个宇宙飞船,这个飞船可以在二维的空间上根据其当前的坐标进行移动,其坐标(横纵坐标)可以使用原子操作进行读取。这样,我们在一次移动操作时,至少有两 个需要被读取或修改的数据。这种条件足以让我们系统的并发性能进行测试。
|
1
2
3
4
5
|
public interface Spaceship{ int readPosition(final int[] coordinates); int move(final int xDelta, final int yDelta);} |
如果不使用不可修改(immutable)的坐标对象,上面的接口定义可以更清晰一些。但是我希望保留它,这样该接口不会产生无效对象。同时,这样做还可以更明确地表明该接口会修改多个内部变量。此外,这个接口还可以很容易地在保持原子性的前提下扩展到三维空间。
我实现了多种不同的并发算法来操作飞船,并用一个测试程序来执行不同的实现。代码和所有的执行结果可以这里找到。
测试程序将按照超多态分发(megamorphic dispatch)模式依次运行不同的实现。这是为了防止 JVM 在运行时优化并发调用的接口,例如用函数实现替换函数接口、弱化锁机制或者展开循环。这些优化会影响我们的测评结果。
每种并发算法的实现都在四种不同的线程环境下进行了测试,并表现出不同的特征:
- 单读取、单写入
- 双读取、单写入
- 三读取、单写入
- 双读取、双写入
所有的测试均在下面环境中进行,Java 1.7.0_25 64-位、Linux 3.6.30 、双核 2.2GHz Ivy Bridge
i7-3632QM
CPU。每一种实现的测试均重复5次以确保结果的稳定性,具体的吞吐量是以5秒为周期进行测量。下面的结果显示了综合5次测试结果后的每秒平均吞吐量。为
了贴近通常的 Java
部署环境,测试中没有配置线程绑定(由指定核运行)或对CPU的分工进行划分,因为对CPU的使用的划分在极大程度上会降低实现间的差异。
注意: 使用其他CPU和操作系统可能导致迥异的测试结果。
图1
图2
图3
图4
上图中的原始数据可以在这里找到。
分析
真正让我惊讶的是 ReentrantReadWriteLock 在测试所表现出的性能。对于
ReentrantReadWriteLock,最适合的应用场景应该是当系统中存在有大量的读取需求以及极少的写入需求时(如上图2、图3所示)。下面
是这次测试的主要收获:
- StampedLock 是对现有锁机制实现的一个很好补充,当更多的读取者参与竞争时尤其如此。
- StampedLock 有着复杂的API,可能会引起对其方法或者锁定动作的误用。
- 在解决两个线程间的竞争问题时,synchronized 是一个不错的通用的锁机制。
- 如之前提到的,当线程数增加时ReentrantLock 可以作为一个不错的通用锁机制解决竞争问题。
- 在考虑是否选择使用 ReentrantReadWriteLock 时,首先需要进行仔细并恰当的测试来衡量其性能。好比所有重要的决策,都应该根据真实数据来进行评估和决策。
- 无锁实现在提高吞吐量方面的能力远超有锁的同步算法。
总结
无锁技术在有锁同步算法中的应用带来了可喜的结果。在读取对象时采用乐观策略无疑是对无锁算法中的技术的有效利用。
在我教授无锁算法以及实际的开发经历中,无锁技术不仅仅提供了更高的吞吐量——如测试中验证的那样,同时在响应延迟上的抖动上也要较有锁算法小很多。
Results
|
| Figure 1. |
|
| Figure 2. |
|
| Figure 3. |
|
| Figure 4. |
转载 http://www.importnew.com/7774.html
加锁并发算法 vs 无锁并发算法的更多相关文章
- 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- (转载)java高并发:CAS无锁原理及广泛应用
java高并发:CAS无锁原理及广泛应用 版权声明:本文为博主原创文章,未经博主允许不得转载,转载请注明出处. 博主博客地址是 http://blog.csdn.net/liubenlong007 ...
- lock free(无锁并发)是什么
一.非阻塞同步(Non-blocking Synchronization) 1. 无锁编程 / lock-free / 非阻塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线 ...
- Lock Free (无锁并发)
CAS( compare and swap) 原子操作,保证了如果需要更新的地址没有被其他进程(线程)改动过,那么它可以安全的写入.而这也是我们对于某个数据或者数据结构加锁要保护的内容,保证读写的一致 ...
- 无锁并发框架Disruptor学习入门
刚刚听说disruptor,大概理一下,只为方便自己理解,文末是一些自己认为比较好的博文,如果有需要的同学可以参考. 本文目标:快速了解Disruptor是什么,主要概念,怎么用 1.Disrupto ...
- 基于无锁的C#并发队列实现(转载)
最近开始学习无锁编程,和传统的基于Lock的算法相比,无锁编程具有其独特的优点,Angel Lucifer的关于无锁编程一文对此有详细的描述. 无锁编程的目标是在不使用Lock的前提下保证并发过程中共 ...
- 基于无锁的C#并发队列实现
最近开始学习无锁编程,和传统的基于Lock的算法相比,无锁编程具有其独特的优点,Angel Lucifer的关于无锁编程一文对此有详细的描述. 无锁编程的目标是在不使用Lock的前提下保证并发过程中共 ...
- 【漫画】CAS原理分析!无锁原子类也能解决并发问题!
本文来源于微信公众号[胖滚猪学编程].转载请注明出处 在漫画并发编程系统博文中,我们讲了N篇关于锁的知识,确实,锁是解决并发问题的万能钥匙,可是并发问题只有锁能解决吗?今天要出场一个大BOSS:CAS ...
- 如何在高并发环境下设计出无锁的数据库操作(Java版本)
一个在线2k的游戏,每秒钟并发都吓死人.传统的hibernate直接插库基本上是不可行的.我就一步步推导出一个无锁的数据库操作. 1. 并发中如何无锁. 一个很简单的思路,把并发转化成为单线程.Jav ...
随机推荐
- 消息 14607,级别 16,状态 1,过程 sp_send_dbmail,第 141 行 profile 名称无效
错误:消息 14607,级别 16,状态 1,过程 sp_send_dbmail,第 141 行profile 名称无效 原因: 用SA帐户是可以发送邮件的,但换了另外一个帐户后却提示以上错误. 解决 ...
- java并发中的锁
java中的锁,最基本的是Lock接口. Lock接口中的方法,主要是: lock(): 获取锁,lock()方法会对Lock实例对象进行加锁,因此所有对该对象调用lock()方法的线程都会被阻塞,直 ...
- Python3 chr() 函数
Python3 chr() 函数 Python3 内置函数 描述 chr() 用一个整数作参数,返回一个对应的字符. 语法 以下是 chr() 方法的语法: chr(i) 参数 i -- 可以是 10 ...
- 在Linux下配置jdk的环境变量
jdk下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 在根目录新建s ...
- 使用生活实例理解Asp.net运行时
学习编程语言,掌握面向对象的编程思想尤为重要,一旦理解了面向对象的这种概念,那么好些地方拿到生活中去理解,就容易的多了.书本上的枯燥干涩的语言,对于好多人来说,即难懂,更难长时间牢牢记得.但是编程语言 ...
- 鼠标经过的图片高亮显示,其余变暗效果[xyytit]
初始代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
- 查看CPU序列号以及系统信息
CPU序列号 wmic cpu get processorid 现在也不唯一,比如联想同款机器,因为CPU批量生产,id也是一样 操作系统信息 systeminfo 查看硬件信息 dxdi ...
- sql批量修改字段内容的语句-SQL技巧
--update '表名' set 要修改字段名 = replace (要修改字段名,'被替换的特定字符','替换成的字符')--update tRecord set columnName = rep ...
- discuz模板引擎语法
论坛的首页模板:forum/discuz.htm 版块的内容模板:forum/forumdisplay.htm 主题的查看模板:forum/viewthread.htm 帖子的内容模板:forum/p ...
- ssh的无密码登录
实现步骤如下: 1 生成一对公钥和私钥 $ ssh-keygen #以上命令等价于 ssh-keygen -t rsa #-t:指定密钥的类型,默认为SSH-2 的rsa类型; 运行上面的命令后,系统 ...