赞
踩
synchronized
在JDK5之前,Java保证线程同步的方式是独占锁synchronized,这种锁存在很多问题:
1)一个线程持有锁会导致其他需要该锁的线程挂起(阻塞),当前线程释放锁其他阻塞线程再度获取锁会导致系统上下文切换和CPU调度延时
3)如果一个优先级高的线程挂起等待一个优先级低的线程释放锁,优先级混乱
在JDK5之后引入了CAS。
CAS(compare and swap)比较并交换
是计算机中用于实现多线程同步的原子指令。通过查看java.util.concurrent.atomic可以发现大量的atomic类,这些类有一个相同的方法compareAndSet
通过查看这些方法我们发现最终调用的都是JNI本地方法,实际上CAS就是利用计算机系统CAS指令,借助JNI实现Java的非阻塞算法。那么CAS是怎么实现多线程同步的?
CAS有三个操作数,地址V、地址V指向的原始值A、待修改值B。判断V地址存储的值是否等于A,如果结果为true,则将地址V的指向的值修改为B,如果结果为false,则将地址V指向的值修改为A,重新判断,直到为true再将地址V指向的值修改为B,这个重试过程叫自旋。所以不难理解,对于CAS,当前线程是能够感知到要修改的目标值是否被其他线程修改过,如果被修改了,直接获取其他线程修改的值再次进行修改,这是CAS的基本原则。
CAS(compare and swap)缺陷
1)ABA问题,假如V指向=1、A = 1、B= 2,有两个线程同时CAS。
线程1CAS后V指向=2、A=2,同时线程1又CAS一次将V指向=1、A=1,线程2再次CAS时依然能够成功,因为线程2无法判断值是否改变,但其实值已经改变过,这样会造成CAS结果不准确,这个问题的解决方案其实很简单,对每次CAS增加一个版本号变量,每CAS一次版本号增加一次,这样就成功的解决了ABA问题。
2)自旋时间过长,增加CPU开销
3)只能保证一个共享变量的原子操作,如果是多个共享变量,atomic包中引入了普通对象的包装类AtomicReference,它可以保证你在修改对象引用时的线程安全。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。