jmm synchronized的内存语义和它是如何保证并发三大特性的

synchronized实现可见性

jmm中的happens-before规则中有一条监视器规则:对同一个监视器的解锁,happens-before于对该监视器的加锁

1、线程解锁前,必须把工作内存中共享变量的最新值刷新到主内存中
2、线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值(注意:加锁与解锁需要是同一把锁)

happens-before规则,我的这篇文章中有提到
https://www.jianshu.com/p/bb894b1fe2e6

synchronized实现原子性

synchronized实现原子性需要多个线程之间使用相同的对象锁。这样临界区里所有的就代码可以看做一个原子操作。
比如: A、B两个线程都使用 Object.class 对象来做对象锁。那么B线程无法读到 A线程的中间状态。
如果使用的是不同的对象锁或者有一个线程不使用synchronized,那么就不存在原子性!

synchronized实现有序性

有序性包括两个方面 “指令重排序” 和 “工作内存与主内存同步延迟” 现象,synchronized实现的只是禁止“工作内存与主内存同步延迟” ,并不会禁止指令重排序。在java中只有volatile关键字才能禁止指令重排序

为什么synchronized不能禁止指令重排序又能保证有序性?

synchronized不能防止指令重排序,但是能保证有序性,这和volatile实现有序性的方式不同

  • synchronized是通过互斥锁来保证有序性的,同步块里是单线程的。按照as-if-serial语义:即在单线程下不管怎么重排序,程序的执行结果不能被改变。
  • 而volatile是通过内存屏障实现的有序性,即防止指令重排序来保证有序性。
注意: synchronized 无法禁止内部区域代码的`指令的重排序优化!

总而言之就是, synchronized 块里的非原子操作依旧可能发生指令重排

关于as-if-serial语义可以看看我这篇文章
https://www.jianshu.com/p/40cb45484f1e

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容