[学习笔记]java虚拟机(四)

书接上文,虚拟机(三)

无锁

非阻塞同步有许多方法:如ThreadLocal,每个线程拥有各自独立的变量副本;CAS,Compare And Swap。

CAS

基于CAS的无锁并发控制,是更具性能的方式。CAS算法包括三个参数,CAS(V,E,N)。V表示要更新的变量,E表示该变量预期的值,N表示要赋予的新值。仅当V的值等于E的值时,才将V的值设为N,若不同,则该线程被告知失败,允许再次尝试或放弃操作。返回值为当前V的真实值。

java中的原子操作类的实现采用了CAS算法。java.util.concurrent.atomic包下。

LongAdder

CAS已经极大提升了性能,但欲望无止境。jdk1.8引入了LongAdder类,也是使用了CAS。但是前面提到的原子操作类的实现机制是:在一个死循环里面,不断尝试修改目标值,直到修改成功。但当影响竞争激烈,大量修改失败时,会进行多次循环尝试,性能会受到影响。

第二篇中提到了锁的优化,CAS虽然不涉及锁,但减小锁粒度等方法思路仍可以使用。仿造ConcurrentHashMap将热点数据分离,将value分离成一个数组,每个线程通过哈希等算法映射到一个数字进行计数,最终的计数结果为数组的求和累加。


java内存模型

并发程序需要保证数据访问的一致性。jvm的基本原则和特性解释并规范了多线程的各种情况。

原子性

原子代表不可分割,原子操作不可中断,不能被多线程干扰。
实现方法:volatile修饰参数。

有序性

现代CPU进行了许多优化,比如指令重排。重排会导致多线程中的语义出现不一致。
解决方法:synchronized关键字修饰方法。

可见性

可见性指的是当一个线程修改了一个变量的值时,另外一个线程可以马上得知这个修改。而因为编译器的优化,部分变量的值可能会被寄存器或Cache缓存,每个CPU都拥有独立的寄存器和Cache,从而导致其他线程无法立即发现这个修改。
解决方法:volatile关键字,或synchronized关键字。

Happens-Before原则

指令重排不可违背的原则:

  1. 程序顺序原则
  2. volatile原则
  3. 锁规则
  4. 传递性
  5. 线程的start()方法先于它的每个动作
  6. 线程的每个操作先于线程的终结
  7. 线程的中断先于被中断线程的代码
  8. 对象的构造函数执行结束先于finalize()方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值