java多线程基础

java多线程基础

线程安全性

当多个线程访问莫个类时,这个类始终都能表现出正确的行为,那么这个类就是线程安全的。
在线程安全的类中封装了必要的同步机制,因此客户端无须进一步采取同步措施。
无状态对象一定是线程安全的。

保证线程安全性的三种方式

  1. 不在线程之间共享状态变量
  2. 将状态变量修改为不可变
  3. 访问状态变量时使用同步

原子性

在单核CPU中, 能够在一个指令中完成的操作都可以看作为原子操作, 因为中断只发生在指令间。
java中对于非long和double基本数据类型的”简单操作”都可以看作是原子的。
long和double都是64位,jmm不保证操作的原子性。

可见性

变量读取到的值,总是任何线程对该变量最后写入的值。
加锁不只局限于互斥行为,还包括了内存可见性。为了确保所有线程都能共享到变量最新的值,因此读或者写都必须在一个锁上同步。

顺序性

在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。
Java内存模型具备一些先天的“有序性”,即不需要通过任何手段就能够得到保证的有序性,这个通常也称为 happens-before 原则。
如果两个操作的执行次序无法从happens-before原则推导出来,那么它们就不能保证它们的有序性,虚拟机可以随意地对它们进行重排序

线程封闭和栈封闭

线程封闭:变量只属于某个线程,例如通过 ThreadLocal来保持的线程变量。
栈封闭是线程封闭的一种特例,在栈封闭中,只有通过局部对象才能访问对象。

不变性

不可变的对象一定是线程安全的。不可变不等于final,即使对象所有的域都是final的,对象也依然可能是可以变得。
final 修饰引用类型只代表该引用不可变,不代表引用的对象不可变。final修饰简单值类型能保证是不可变的。
满足一下条件对象才是不可变的。

  • 对象创建以后不可以修改
  • 对象创建以后不可以修改
  • 对象是正确创建的(this没有溢出)