File tree Expand file tree Collapse file tree 6 files changed +66
-0
lines changed Expand file tree Collapse file tree 6 files changed +66
-0
lines changed Original file line number Diff line number Diff line change
1
+ # 23、能聊聊volatile关键字的原理吗?
2
+ 内存模型 -> 原子性、可见性、有序性 -> volatile
3
+
4
+
5
+
6
+ 讲清楚volatile关键字,直接问你volatile关键字的理解,对前面的一些问题,这个时候你就应该自己去主动从内存模型开始讲起,原子性、可见性、有序性的理解,volatile关键字的原理
7
+
8
+
9
+
10
+ volatile关键字是用来解决可见性和有序性,在有些罕见的条件之下,可以有限的保证原子性,他主要不是用来保证原子性的
11
+
12
+ ![ volatile使用代码] ( images/23/01.png )
13
+
14
+ 可见性,概念进行了加强和深化,volatile在可见性上的作用和原理,有一个很清晰的了解
15
+
16
+
17
+
18
+ 在很多的开源中间件系统的源码里,大量的使用了volatile,每一个开源中间件系统,或者是大数据系统,都多线程并发,volatile
19
+
20
+ ![ kafka源码使用volatile] ( images/23/01.png )
Original file line number Diff line number Diff line change
1
+ # 24、你知道指令重排以及happens-before原则是什么吗?
2
+ volatile关键字和有序性的关系,volatlie是如何保证有序性的,如何避免发生指令重排的
3
+
4
+ ![ volatile指令重排] ( images/24/01.png )
5
+
6
+ java中有一个` happens-before ` 原则:
7
+
8
+ 编译器、指令器可能对代码重排序,乱排,要守一定的规则,happens-before原则,只要符合happens-before的原则,那么就不能胡乱重排,如果不符合这些规则的话,那就可以自己排序
9
+
10
+ * 1、程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
11
+
12
+ * 2、锁定规则:一个unLock操作先行发生于后面对同一个锁的lock操作,比如说在代码里有先对一个lock.lock(),lock.unlock(),lock.lock()
13
+
14
+ * 3、volatile变量规则:对一个volatile变量的写操作先行发生于后面对这个volatile变量的读操作,volatile变量写,再是读,必须保证是先写,再读
15
+
16
+ * 4、传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
17
+
18
+ * 5、线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作,thread.start(),thread.interrupt()
19
+
20
+ * 6、线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
21
+
22
+ * 7、线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
23
+
24
+ * 8、对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始
25
+
26
+
27
+ 上面这8条原则的意思很显而易见,就是程序中的代码如果满足这个条件,就一定会按照这个规则来保证指令的顺序。
28
+
29
+
30
+
31
+ 很多同学说:好像没听懂,模模糊糊,这些规则写的非常的拗口,晦涩难懂,在面试的时候比如面试官问你,happens-before原则,你必须把8条规则都背出来,反问,没有任何一个人可以随意把这个规则背出来的
32
+
33
+ 规则制定了在一些特殊情况下,不允许编译器、指令器对你写的代码进行指令重排,必须保证你的代码的有序性
34
+
35
+
36
+ 但是如果没满足上面的规则,那么就可能会出现指令重排,就这个意思。
37
+
38
+ ![ volatile指令重排] ( images/24/02.png )
39
+
40
+ 这8条原则是避免说出现乱七八糟扰乱秩序的指令重排,要求是这几个重要的场景下,比如是按照顺序来,但是8条规则之外,可以随意重排指令。
41
+
42
+ 比如这个例子,如果用volatile来修饰flag变量,一定可以让prepare()指令在flag = true之前先执行,这就禁止了指令重排。
43
+
44
+ 因为volatile要求的是,volatile前面的代码一定不能指令重排到volatile变量操作后面,volatile后面的代码也不能指令重排到volatile前面。
45
+
46
+ 指令重排 -> happens-before -> volatile起到避免指令重排
You can’t perform that action at this time.
0 commit comments