Java内存模型中的happen-before是什么?
Java语言在设计之初就引入了线程的概念,以充分利用现代处理器的计算能力,这既带来了强大、灵活的多线程机制,也带来了线程安全等令人混淆的问题,而Java内存模型(Java Memory Model,JMM)为我们提供了一个在纷乱之中达成一致的指导准则。
今天我要问你的问题是,Java内存模型中的happen-before是什么?
典型回答
-
Happen-before关系,是Java内存模型中保证多线程操作可见性的机制,也是对早期语言规范中含糊的可见性概念的一个精确定义 -
它的具体表现形式,包括但远不止是我们直觉中的synchronized、volatile、lock操作顺序等方面,例如:
- 线程内执行的每个操作,都保证happen-before后面的操作,这就保证了基本的程序顺序规则,这是开发者在书写程序时的基本约定
- 对于volatile变量,对它的写操作,保证happen-before在随后对该变量的读取操作
- 对于一个锁的解锁操作,保证happen-before加锁操作
- 对象构建完成,保证happen-before于fnalizer的开始动作
- 甚至是类似线程内部操作的完成,保证happen-before其他Thread.join()的线程等
-
这些happen-before关系是存在着传递性的,如果满足a happen-before b和b happen-before c,那么a happen-before c也成立 -
前面我一直用happen-before,而不是简单说前后,是因为它不仅仅是对执行时间的保证,也包括对内存读、写操作顺序的保证。仅仅是时钟顺序上的先后,并不能保证线程交互的可见性
考点分析
- 今天的问题是一个常见的考察Java内存模型基本概念的问题,我前面给出的回答尽量选择了和日常开发相关的规则
- JMM是面试的热点,可以看作是深入理解Java并发编程、编译器和JVM内部机制的必要条件,但这同时也是个容易让初学者无所适从的主题。对于学习JMM,我有一些个人建议:
- 明确目的,克制住技术的诱惑。除非你是编译器或者JVM工程师,否则我建议不要一头扎进各种CPU体系结构,纠结于不同的缓存、流水线、执行单元等。这些东西虽然很酷,但其复杂性是超乎想象的,很可能会无谓增加学习难度,也未必有实践价值
- 克制住对“秘籍”的诱惑。有些时候,某些编程方式看起来能起到特定效果,但分不清是实现差异导致的“表现”,还是“规范”要求的行为,就不要依赖于这种“表现”去编程,尽量遵循语言规范进行,这样我们的应用行为才能更加可靠、可预计。
|