JMM模型

一、指令重排序

1.javac生成字节码时,及字节码被JIT编译器编译成本地代码时,会进行指令的重排序
2.处理器可以乱序和并发执行指令
3.如果没有充分同步,在另一个线程中完全可以看到一个线程代码执行顺序和“理所当然”的顺序不一致

以上的程序,可能会打印出x=0,y=0;x=1,y=0;x=0,y=1;x=1,y=1
4.要使程序的执行可以预测,JMM必然会做一些规定限制,那就是happens-before规则,final初始化规则

二、happens-before

1.是一种偏序关系

2.规则:

(1)同一个线程中的每个action都happens-before于出现在其后的任何一个action
(2)对一个监视器的解锁happens-before于每一个后续对同一个监视器的加锁
(3)对volatile字段的写入操作happens-before于每一个后续的同一个字段的读操作
(4)Thread.start()的调用会happens-before于启动线程里面的动作
(5)Thread中的所有动作都happens-before于其他线程检查到此线程结束或者Thread.join()中返回或者Thread.isAlive()==false
(6)一个线程调用另一个线程的interrupt happens-before于被中断的线程发现中断(通过抛出InterruptedException,或者调用isInterrupted和interrupted)
(7)一个对象构造函数的结束happens-before与该对象的finalizer的开始
(8)如果A动作happens-before于B动作,而B动作happens-before与C动作,那么A动作happens-before于C动作

3.代码分析:

a)利用规则(1)、(3)和(8)分析
b)result=v < releaseShared(0)
c)acquireSharedInterruptibly(0) < return result
d)在releaseShared(0)、 acquireSharedInterruptibly(0)中会操作AQS中的一个volatile变量
e)releaseShared(0) < acquireSharedInterruptibly(0)
f)因此,result不设置为volatile类型也可以具有volatile类型的可见性

三、final初始化规则

1.当构造函数执行完成后,对象创建正确,无论怎样发布,所有线程都能看到final域的值,并且任何通过final域触及到的变量(一个final的数组中的元素,一个final的HashMap中的元素),也都是可见的
2.保证了不变对象可以通过任何方式发布

四、double-check lock

1.起源于为了改善synchronized的单例的性能

2.由于外层的resource未进行同步,因此即使resource的引用可见了,但是resource的状态不一定可见,因此可能一个线程读到resource并未构造成功
3.改进:Holder模式,利用了在ClassLoader加载类时才会初始化类的static成员


五、ABA问题

(1)cas中,内存V的值由A改为B,又改为A,那么按照compareAndSet(T oldValue, T newValue),由于内存V没有版本号,所以cas会成功,因为忽略过程来看,内存V的值没有变化还是A
(2)AtomicStampedReference利用版本化方案,替代AtomicReference解决这一问题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值