1.原子性
对于涉及共享变量访问的操作,若该操作从其执行线程以外的任意线程来看是不可分割的,那么该操作就是原子操作,相应地我们称该操作具有原子性 (Atomicity)。原子操作的“不可分割“包括以下两层含义。
- 访问(读、写)某个共享变量的操作从其执行线程以外的任何线程来看,该操作要么已经执行结束要么尚未发生,即其他线程不会“看到“该操作执行了部分的中间效果。
- 访问同—组共享变量的原子操作是不能够被交错的。
java中实现原子性的两种方式:
- 锁(Lock)。锁具有排他性,即它能够保障一个共享变量在任意一个时刻只能够被一个线程访问 。这就排除了多个线程在同一时刻访问同一个共享变量而导致干扰与冲突的可能。
- 处理器提供的专门CAS (Compare-and-Swap) 指令。CAS指令实现原子性的方式与锁实现原子性的方式实质上是相同的,差别在于锁通常是在软件这一层次实现的,而CAS是直接在硬件(处理器和内存)这一层次实现的,它可以被看作“硬件锁” 。
此外,long型和double型以外的任何类型的变量的写操作都是原子操作,即对基础类型 (long/double 除外,仅包括 byte 、 boolean 、 short 、 char 、 float 和 int) 的变量和引用型变量的写操作都是原子的 。这点由 Java 语言规范 (JLS , Java Language Specification) 规定。由 Java 虚拟机具体实现 。
2.可见性
可见性就是指一个线程对共享变量更新的结果对于读取相应共享变量的线程而言是否可见的问题。产生可见性问题的原因:JIT编译器对代码的优化、计算机存储系统。
Java语言规范 (JLS, Java Language Specification) 保证,1.父线程在启动子线程之前对共享变量的更新对于子线程来说是可见的。2.一个线程终止后该线程对共享变量的更新对于调用该线程的 join 方法的线程而言是可见的。
3.有序性
有序性 (Ordering) 指在什么情况下一个处理器上运行的一个线程所执行的内存访问操作在另外一个处理器上运行的其他线程看来是乱序的 (Out of order)。所谓乱序,是指内存访问操作的顺序看起来像是发生了变化。造成有序性问题的原因:指令重排序、存储子系统重排序。