线程安全问题
非线程安全主要是指多个线程对同一个对象的实例变量进行操作时,会出现值被更改,值不同步的情况。
线程安全问题表现为三个方面:原子性,可见性和有序性
-
原子性
原子(Atomic)就是不可分割的意思,原子操作的不可分割有两层含义:- 访问某个共享变量的操作从其他线程来看,该操作要么已经执行完毕,要么尚未发生。
- 访问同一组共享变量的原子操作是不能够交错的。
Java 有两种方式实现原子性:一种是使用锁;另一种利用处理器的 CAS(Compare and Swap)指令。
锁具有排他性,保证共享变量是在某一时刻只能被一个线程访问。
CAS 指令直接在硬件(处理器和内存)层次上实现,看作是硬件锁。 -
可见性
在多线程环境中,一个线程对某个共享变量进行更新之后,后续的其他线程可能无法立即读取到这个更新的结果,这就是线程安全问题的另外一种形式:可见性(visibility)。
如果一个线程对共享变量更新后,后续访问该变量的其他线程可以得到更新的结果,称这个线程对共享变量的更新对其他线程可见,否则称这个线程对共享变量的更新对其他线程不可见。
多线程程序因为可见性问题可能会导致其他线程读取到了旧数据(脏数据)。 -
有序性
有序性(Ordering)是指在什么情况下 一个处理器上运行的一个线程所执行的内存访问操作在另一个处理器运行的其他线程看来是乱序的(Out of Order)。