深入理解并发编程三大特性

前言

在面试中,经常会被面试官问到,请你说说并发编程的三大特性,不得不承认我毕业的时候面试被问到的概率是50%,那个时候我依稀记得我还年轻,我傻傻的回答了百度到的简单答案。然后面试官看着我 ,我看着他,似乎哪里见过,似乎又未曾。他突然眼睛瞪大想说什么似乎又不想说什么,我一脸期待,以为终于等到了我梦里的那个他。然而他却给我说了,那三个字,等通知。 从此这三个字深深的印在了我的心中。然后现在你们就看到了我在这里编故事。废话不多说,直接冲。

一、并发编程三大特性

既然要说锁,肯定要先说说并发编程的三大特性,网上也有很多解释,但是很多解释很苍白很难深入理解这三大特性。当然也有很多好的博客解释得很好,这个的话还是看自己怎么去理解,

原子性

在解释原子性时,很多博客都会解释不可分割,全部成功或者全部失败,这是网上大部分的解释, 既然提到了不可分割,按字面意思来理解的话就有点抽象,下面我们通过银行取钱的流程图来理解

image.png 上图是按我自己的理解去解释的,如果各位大佬们觉得很难理解的话,可以参照下面官方一点的解释

image.png

可见性

理解可见性还得从Java内存模型说起(JMM),屁话不多放上图解释

image.png

由Java内存模型可以看出在多线程并发操作同一变量是不安全的,为什么不安全?看图

image.png

如何解决线程之间可见性问题???

synchronized

还是屁话不多说,还是那句话---上图

image.png

volatile

volatile是通过加入内存屏障和禁止重排序优化来实现可见性的 但是要注意的是volatile能够保证volatile变量的可见性,但是不能保证volatile变量复合操作的原子性。

对volatile关键字修饰变量进行写操作时,会在写操作后加入一条store屏障指令,将本地内存中的共享变量刷新到主内存;
对volatile关键字修饰变量进行读操作时,会在读操作前加入一条load屏障指令,从主内存中读取共享变量
简单点说就是,volatile变量在每次被线程访问时,都强迫从主内存中重读该变量的值,而当该变量发生变化时,又会强迫线程将最新的值刷新到主内存。这样任何时刻不同的线程总能看到该变量的最新值。

废话不多说还是那句话上图

image.png

有序性

在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。

在Java里面,可以通过volatile关键字来保证一定的“有序性”。另外可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性。 关于使用volatile关键字来保证有序性可以参考我另外一篇文章的内容,最后面会讲到,这里废话我就不多说了# 重识单例模式(双重检查锁定/延迟初始化)

猜你喜欢

转载自juejin.im/post/7041598068113801252