线程间有两种通信机制:共享内存和消息传递。
Java采用共享内存模型。
happens-before规则
如果一个操作happens-before另一个操作,那么第一个执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个之前。(JMM对程序员的承诺)
两个操作之间存在happens-before关系,并不意味着Java平台的具体实现必须要按照happens-before关系指定的顺序来执行。如果重排序之后的执行结果,与按happens-before关系来执行的结果一致,那么这种重排序并不非法(JMM对编译器和处理器重排序的约束原则)
1.程序顺序规则
2.监视器锁规则:对一个锁的解锁happens-before随后对这个锁的加锁
3.volatile变量规则:对一个volatile域的写happens-before于任意后续对这个volatile域的读。
4.传递性
5.start规则:线程A中执行ThreadB.start(),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。
6.join规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
as-if-serial规则
不管怎么重排序,程序的执行结果不能被改变。(单线程内)
两个规则这么做的目的,都是为了在不改变程序执行结果的前提下,尽可能地提高程序执行的并行度。
volatile具有下列特性
可见性。对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
原子性。对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。
线程A写一个volatile变量,随后线程B读这个volatile变量,这个过程实质上是线程A通过主内存向线程B发送消息。
volatile内存语义的实现
每个volatile写操作前面插入一个StoreStore屏障,禁止上面的普通写和下面的volatile写重排序。
每个volatile写操作的后面插入一个StoreLoad屏障,防止上面的volatile写与下面可能有的volatile读/写重排序
每个volatile读操作的后面插入一个LoadLoad屏障,禁止下面所有的普通读操作和上面的volatile读重排序。
每个volatile读操作的后面插入一个LoadStore屏障,禁止下面所有的普通写操作和上面的volatile读重排序。