Java内存模型与线程

1.硬件的效率
计算机的性能大部分浪费在IO操作上,cachc是内存和处理器间的缓冲,目的是为了读写操作尽量接近运算器的运行速度。
但是高速缓冲带来了新的问题“缓冲一致性”。
Java内存模型与线程_第1张图片
为了解决这一问题,读写操作需要根据协议来进行(MSI、MOSI),处理器可能会对输入代码进行乱序执行优化,处理器会将乱序执行的结果重组,保证结果一致性。java虚拟机的指令重排序。
2.java 内存模型
java虚拟机定义了一种java内存模型(JMM)来屏蔽各种硬件和操作系统的内存访问差异,以实现java程序在各种平台下都能达到一致的内存访问效果。
Java内存模型与线程_第2张图片
3.内存间交互操作:
lock:作用主内存的变量,把一个变量标识为一条线程独占的状态。
unlock:作用在主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
read:读取主内存的变量,把一个变量的值从主内存传输到线程工作的内存中,一边随后的load动作。
load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入到工作内存的变量副本中。
use:作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。
assign:作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时会执行这个操作。
store:作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用。
write:作用于主内存的变量,它把store操作从工作内存得到的变量值放入到主内存中。

对应long,double这两操作的load,read,store,write的原子性。

原子性:由java内存模型来直接抱走的原子性操作包括read、load、assign、use、store、write。大致任务基本数据类型的访问读写都具备原子性。
可见性:当一个线程修改了共享变量,其他下次能够立即得知这个修改。
可见性的关键字:synchronized,voliate,final
有序性:synchronized,voliate(禁止指令重排序)

4.java与线程
java线程Thread中,大多数关键方法都声明了native,与平台操作系统相关。
线程的实现:使用内核线程实现、使用用户线程实现、使用用户线程加轻量级进程混合使用。
这里不在深入,可以参考《深入理解java虚拟机》

Java线程调度
协同式线程调度:线程的执行时间由线程自身控制,线程工作执行完以后通知系统切换到另外一个线程上。好处:简单。坏处:线程执行时间不可控制,造成阻塞。
抢占线程调度:由系统分配执行时间,线程的切换由线程本身控制,不会有一个线程导致真个进程阻塞的问题。

4.线程安全与锁优化
不可变:不可变对象一定是线程安全的。如果共享的是基本数据类型,只要定义时使用final关键字修饰就可以保证它的不可变性。如果共享的是一个对象,需要保证对象的行为不会对其专业产生任何影响。
绝对线程安全:不管运行时环境如何,调用者都不需要任何额外的同步措施。
相对线程安全:需要保证这个对象单独的操作是线程安全的,我们在调用的时候不需要再进行额外的保护措施。如vector,HashTable
线程兼容:指对象本身不是线程安全的,但是可以通过调用正确的同步方法来保证对象在并发环境中可以被安全的使用,如arrayList。
线程对立:无论调用端采取何种同步措施,都无法保证多线程环境中并发使用的代码。如suspend和resume方法。

锁优化
自旋锁与自适应自旋:互斥同步对性能造成最大的影响是阻塞的实现,挂起线程和恢复线程的操作都需要大量的开销,自旋锁让一个线程执行自旋(循环忙)。
Java内存模型与线程_第3张图片
锁消除:对检测到不可能存在共享数据竞争的锁进行消除。
锁粗化:如果存在连续加锁的地方,锁代码加大。
轻量级锁:如tryLock,volatile.
偏向锁:偏向第一个获取它的线程。

你可能感兴趣的:(java多线程)