Java线程安全

线程安全

  • 控制多个线程对某个资源的有序访问或修改
  • 解决两个主要的问题:可见性有序性

####synchronized关键字
synchronized关键字做为多线程并发环境的执行有序性的保证手段之一

synchronized(锁){  
        临界区代码 
 }   

每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程,当一个被线程被唤醒 (notify)后,才会进入到就绪队列,等待cpu的调度。

####volatile关键字
volatile是java提供的一种同步手段,只不过它是轻量级的同步,只能保证多线程的内存可见性,不能保证多线程的执行有序性。
任何被volatile修饰的变量,都不拷贝副本到工作内存,任何修改都及时写在主存。不能保证原子性

要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:

  1. 对变量的写操作不依赖于当前值。
  2. 该变量没有包含在具有其他变量的不变式中

volatile只保证了可见性,所以Volatile适合直接赋值的场景:

public class VolatileTest{  
  public volatile int a;  
  public void setA(int a){  
  this.a=a;  
  }  
} 

在没有volatile声明时,多线程环境下,a的最终值不一定是正确的,因为this.a=a;涉及到给a赋值和将a同步回主存的步骤,这个顺序可能被打乱。如果用volatile声明了,读取主存副本到工作内存和同步a到主存的步骤,相当于是一个原子操作。所以简单来说,volatile适合这种场景:

一个变量被多个线程共享,线程直接给这个变量赋值。这是一种很简单的同步场景,这时候使用volatile的开销将会非常小。

参考文章:

分享到