原子变量

JAVA 并发编程实践 - 原子变量与非阻塞同步机制 笔记

大兔子大兔子 提交于 2019-12-06 12:30:06
非阻塞算法: 利用底层的源自机器指令(比如CAS)代替锁来实现数据在并发访问中的一致性。应用于:操作系统和JVM中实现线程/进程调度机制,垃圾回收机制以及锁和其他并发数据结构。 与基于锁的方案相比, 非阻塞算法实现复杂,但是可伸缩性和活跃性拥有优势,多线程竞争相同数据的情况下不用阻塞,可以在更细的类度上进行协调, 减少调度开销, 在非阻塞算法中不存在死锁和活跃性问题。 原子变量提供了与volatile相同的内存语义, 同时支持原子操作, 比基于锁的操作更有可伸缩性。 锁的劣势:竞争锁的线程会挂起和恢复线程, 这样调度和开销会比较大。 Volatile是更轻级别的同步机制,在使用时不会发生上下文切换或者线程调度,但是volatile不能保证构建原子的复合操作,当一个变量依赖于其他变量或者当变量的新值依赖于旧值时, 就不能使用volatile变量。所以不能用来实现计数器和互斥体(mutex). 所得缺点还有线程在等待锁时不能做其他的事情, 这样多线程等待锁时,等待线程被阻塞。如果持有锁的线程优先级别低而请求所得线程优先级别高就会发生优先级别翻转(Priovrity Inversion). JVM对CAS的支持 JAVA5.0之前如果不明确编码,是不能够调用CAS的, 在Java5.0后,引入了底层的支持, 在int, long和对象的引用等类型上都公开了CAS操作

java并发编程——原子变量介绍

强颜欢笑 提交于 2019-11-30 08:20:30
第一部分:原子变量的前世 我们首先看一个例子:产生一个整数序列,每个值都必须是递增唯一的。我们可以用以下代码实现一个: public class UnsafeSequence{ private int value; public int getNext(){ return value++; } } 上面的代码在单线程环境下运行没有任何问题,但是如果在多线程并发访问的情况下它就会有问题。仔细分析getNext方法实际上它包含了三步操作: 第一步:获得当前value值; 第二步:把当前value值+1; 第三步:返回当前value值。 多个线程并发执行上面方法时,返回的value值极有可能是相同的,这显然违背了我们的初衷,所以这个类不是线程安全的。如下图所示: 我们可以用前面讲到的加锁知识把该类修改成线程安全的,最简单的就是给方法加synchronized; public class SafeSequence{ private int value; public synchronized int getNext(){ return value++; } } 修改完以后这个类现在是线程安全的了。如果有线程正在执行getNext方法,那么其他线程就等待当前线程执行完毕后再执行,这样就保证了整个操作的原子性。当这样做还是会给开发人员带来额外的负担,开发人员不得不去思考在哪些调用是需要共享的