1.Java线程间通信对程序员透明,但是其内存可见性问题会引发其他怪异的问题;
2.在并法编程中,需要考虑两个关键问题:1.线程间如何通信 2.线程间如何同步
3.在命令式编程中,线程之间的通信有两种:1.共享内存 2.消息传递
4.共享内存->线程之间共享程序的公共状态,通过读—写该内存中公共状态进行隐式通信
5.消息传递->线程之间没有公共状态,线程之间必须通过发送消息来显示的通信;
6.同步是指控制不同线程间操作发生相对顺序的机制,在共享内存并发模型中,是显示进行的,程序员需要显示的指定某个方法或代码需要在线程之间互斥执行;而消息传递并发模型中,由于消息的发送必须在接受前,同步是隐式的...
7.Java采用的共享内存模型,但是Java线程间通信是隐式进行的,整个过程对程序员透明,故不了理解隐式的线程通信,会遇到内存可见性的问题...
8.Java线程间通信由Java内存模型(JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见...
9.JMM定义了线程和内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory),每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读、写的变量副本;
10.其实本地内存是JMM抽象出来的一个概念,并不是实际存在的,它涵盖了缓存、写缓存区、寄存器和其他硬件和编译器优化
11.线程A与线程B之间通信,需要经历的两个步骤:
a.线程A把本地内存A中更新过的共享变量刷新到主内存中;
b.线程B到主内存中去读取线程A之前更新过的共享变量。
总结:线程A和B之间通信必须要经过主内存,JMM通过控制主内存和每个线程本地内存之间的交互,来问Java程序员提供内存可见性保证...
12.为提高性能,编译器和处理器通常会对指令做出重排序,重排序又分为下面3种:
a.编译器优化重排序,不改变单线程语义的前提下,可以重新安排语句的执行顺序;
b.指令级并行的重排序,若不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序;
c.内存系统的重排序,由于处理器使用缓存和读/写缓冲区,是的加载和存储会发生乱序
总结:a是编译器重排序,bc是处理器重排序,对于编译器,JMM会禁止特定的编译器重排序(例如:不存在数据依赖时),JMM针对处理器重排序,使用插入特定类型的内存屏障(Memory Barriers)
13.常见处理器(x86处理器)只会对Store-Load(Store1先把数据刷新到内存,然后在执行后面的装在指令...)重排序,ARM架构比较奇怪,可能支持Load-Load、Load-Store、Store-Store;
14.happens-before->JSR-133使用该概念来阐述操作之间的内存可见性;
15.happens-before规则:
a.程序顺序规则:一个线程每个操作,happens-before于该线程之后进行其他操作
b.监视器锁规则:一个锁的解锁,happens-before与随后对这个锁再加锁;
c.volatile变量规则:一个volatile域的写,happens-before于任意后序对这个volatile域发生读操作
d.传递性:A happens-before B,B happens-before C => A happens-before C;
总结:happens-before就是展示给程序员理解JMM底层重排序的一种规则...
16.as-if-serial->不管怎么重排,单线程程序的执行结果不能被改变...as-if-serial就是把单线程程序保护了起来