线程安全的基本特性

  1. 原子性:相关操作不会中途被其他线程干扰,一般通过同步机制实现。synchronized 可以保证代码片段的原子性。
  2. 可见性:一个线程修改了某个共享变量,其状态能够立即被其他线程知晓,通常被解释为将线程本地状态反映到主内存上,volatile 就是负责保证可见性的。
    1. 对于线程B中{int m = 1;int n = 2;},当另外一个线程A读取B中m,n的值的时候,可能可以获取到n的值,但获取的是m之前的值(不是被B修改的值),这就是重排序
    2. 失效值:对于变量m=1来说,已经有一个线程A修改了它的值m=2,但是线程B操作的时候,可能读取到的还是m=1,读取的是过期的数据。
  3. 有序性:保证线程内串行语义,避免指令重排等。volatile 关键字可以禁止指令进行重排序优化。


可重入

当某个线程获取被其他线程持有的锁的时候,会被阻塞。

如果一个线程去获取它已经得到的锁的时候,这个请求可以成功。

“重入”代表获取锁的操作的粒度是“线程”。

实现原理

每个锁都关联一个计数器和一个所有者线程。
这个计数器=0,代表当前没有线程持有这个锁。
如果这个时候,一个线程过来请求这个锁,那么计算器+1=1,所有者线程标记为当前的线程。
如果这个时候,同一线程又获取这个锁,那么只需要计数器+1就可以了。
线程退出同步代码块的时候,计数器会-1
计数器=0,释放锁。

发布/逸出

  • 发布:是一个对象可以在当前作用域以外的地方进行使用。
    • 例如一个指向该对象的引用被保存到了其他代码可以访问的地方。
    • 或者在一个非私有代码中返回该引用
  • 逸出:当某一个不该发布的对象被发布
    • 例如this指针逃逸:在构造函数中启动了一个线程,this引用会被这个新线程共享。
    • 非私有方法返回私有的成员变量