1.竞争条件(Race Condition)
多个线程并发访问和操作同一数据且执行结果与访问的特定
顺序有关,竞争的失败者决定该数据的最终值,称为竞争条件
2.Java内存模型(Java Memory Model)
Java平台自动集成了线程以及多处理器技术,这种集成程度比Java以前诞生的计算机语言要厉害很多,
该语言针对多种异构平台的平*立性而使用的多线程技术支持也是具有开拓性的一面,
有时候在开发Java同步和线程安全要求很严格的程序时,往往容易混淆的一个概念就是内存模型。
究竟什么是内存模型?内存模型描述了程序中各个变量(实例域、静态域和数组元素)之间的关系,
以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节。
对象最终是存储在内存里面的,这点没有错,但是编译器、运行库、处理器或者系统缓存
可以有特权在变量指定内存位置存储或者取出变量的值。
【JMM】(Java Memory Model的缩写)允许编译器和缓存以数据在处理器特定的缓存(或寄存器)
和主存之间移动的次序拥有重要的特权,
除非程序员使用了final或synchronized明确请求了某些可见性的保证。
JMM:Java Memory Model(Java内存模型),围绕着在并发过程中如何处理可见性、可见性:JMM提供了volatile变量定义、final、synchronized块来保证可见性。
例如:线程a在将共享变量x=1写入主内存的时候,如何保证线程b读取共享变量x的值为1,
这就是JMM做的事情。JMM通过控制主内存与每个线程的本地内存之间的交互,
来为java程序员提供内存可见性保证。
原子性:JMM提供保证了访问基本数据类型的原子性(其实在写一个工作内存变量到主内存是分主要两步:store、write),
但是实际业务处理场景往往是需要更大的范围的原子性保证,所以模型也提供了synchronized块来保证
有序性:这个概念是相对而言的,如果在本线程内,所有的操作都是有序的,如果在一个线程观察另一个线程,
所有的操作都是无序的,前句是“线程内表现为串行行为”,后句是“指令的重排序”和“工作内存和主内存同步延迟”现象,
模型提供了volatile和synchronized来保证线程之间操作的有序性。
指令重排:在执行程序时为了提高性能,编译器和处理器常常会对指令做重排序(编译器、处理器),就是因为这些重排序
,所以可能会导致多线程程序出现内存可见性问题(数据安全问题)和有序性问题。
JMM是如何处理的呢?
对于编译器,JMM的编译器重排序规则会禁止特定类型的编译器重排序
对于处理器重排序,JMM的处理器重排序规则会要求java编译器在生成指令序列时,
插入特定类型的内存屏障(memory barriers,intel称之为memory fence)指令,
通过内存屏障指令来禁止特定类型的处理器重排序
总之一句话,JMM是通过禁止特定类型的编译器重排序和处理器重排序来为程序员提供一致的内存可见性保证。
A线程具体什么时候刷新共享数据到主内存是不确定的,假设我们使用了同步原语(synchronized,volatile和final),
那么刷新的时间是确定的,例如:线程存A释放锁后会同步到主内存,线程B获取锁后会同步主内存数据
即“A线程释放锁--B线程获取锁”可以实现A,B线程之间的通信
内存屏障(Memory Barrier,或有时叫做内存栅栏,Memory Fence)是一种CPU 特殊指令,
用于控制特定条件下的重排序和内存可见性问题。
Java编译器也会根据内存屏障的规则禁止重排序。