java中的cas实现 (乐观锁机制)
来源:互联网 发布:淘宝店铺招牌源代码 编辑:程序博客网 时间:2024/05/16 08:03
在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁(后面的章节还会谈到锁)。
锁机制存在以下问题:
(1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。
(2)一个线程持有锁会导致其它所有需要此锁的线程挂起。
(3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。
volatile是不错的机制,但是volatile不能保证原子性。因此对于同步最终还是要回到锁机制上来。
独占锁是一种悲观锁,synchronized就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一个更加有效的锁就是乐观锁。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
CAS 操作
上面的乐观锁用到的机制就是CAS,Compare and Swap。
CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
非阻塞算法 (nonblocking algorithms)
一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。
现代的CPU提供了特殊的指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet() 就用这些代替了锁定。
拿出AtomicInteger来研究在没有锁的情况下是如何做到数据正确性的。
private volatile int value;
首先毫无以为,在没有锁的机制下可能需要借助volatile原语,保证线程间的数据是可见的(共享的)。
这样才获取变量的值的时候才能直接读取。
public final int get() {
return value;
}
然后来看看++i是怎么做到的。
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
在这里采用了CAS操作,每次从内存中读取数据然后将此数据和+1后的结果进行CAS操作,如果成功就返回结果,否则重试直到成功为止。
而compareAndSet利用JNI来完成CPU指令的操作。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
整体的过程就是这样子的,利用CPU的CAS指令,同时借助JNI来完成Java的非阻塞算法。其它原子操作都是利用类似的特性完成的。
而整个J.U.C都是建立在CAS之上的,因此对于synchronized阻塞算法,J.U.C在性能上有了很大的提升。参考资料的文章中介绍了如果利用CAS构建非阻塞计数器、队列等数据结构。
CAS看起来很爽,但是会导致“ABA问题”。
CAS算法实现一个重要前提需要取出内存中某时刻的数据,而在下时刻比较并替换,那么在这个时间差类会导致数据的变化。
比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且two进行了一些操作变成了B,然后two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后one操作成功。尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的。如果链表的头在变化了两次后恢复了原值,但是不代表链表就没有变化。因此前面提到的原子操作AtomicStampedReference/AtomicMarkableReference就很有用了。这允许一对变化的元素进行原子操作。
参考资料:
(1)非阻塞算法简介
(2)流行的原子
- java中的cas实现 (乐观锁机制)
- CAS:乐观锁实现
- Redis CAS乐观锁实现
- java AtomicInteger基于CAS的乐观锁实现
- java中的CAS机制
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
- Java 多线程10:CAS 与 AtomicInteger(乐观锁)
- 基于CAS自旋实现的乐观锁
- java学习系列2(并发锁问题-乐观锁与悲观锁以及乐观锁的一种实现方式-CAS)
- java中的cas实现
- memcached cas乐观锁
- CAS乐观锁算法
- CAS 与乐观锁
- Java 多线程:AtomicInteger源码分析——基于CAS的乐观锁实现
- Java 多线程:AtomicInteger源码分析——基于CAS的乐观锁实现
- 乐观锁的一种实现方式——CAS
- 乐观锁的一种实现方式——CAS
- 乐观锁的一种实现方式——CAS
- boost中TCP的客户端发送示例(blocking版)
- Python 基础
- C# .net Gridview 基于Jquery客户端 冻结行 冻结列 (固定行、固定列) js 插件
- 成大事必备9种能力、9种手段、9种心态
- 二级域名的跨域验证
- java中的cas实现 (乐观锁机制)
- PHP柱状图、饼状图和线性图 并支持中文
- 做好B2B行业网站收费服务推广,提高销售额
- Silverlight实例教程 - Out of Browser的自定义应用
- ios计算文件和文件夹的大小
- gcc编译器各种warning 解决方式
- 动态规划 的方法求矩阵乘法的最少计算加括号方式
- Silverlight实例教程 - Out of Browser存取本地文件系统
- Windows Phone 8 的多分辨率应用