从内存角度理解Java线程安全

线程安全:无非就是保证多个线程有序的访问或修改共享数据。

JVM定义了自己的内存模型,对开发者屏蔽了平台操作内存的细节。在Java中,线程之间是无法直接通信的,只能通过共享对象才能相互通信。下面这张图就诠释了Java中线程是如何通信的。

上图包含了连个概念:可见性,有序性。

####可见性
线程A从主内存中拷贝变量x的副本到本地内存中,然后在本地内存中修改x的值,jvm控制将x的值同步到主内存中。线程B也是如此。两个线程就是这样通过主内存共享对象实现两者的通信的。

但是如果他们的执行顺序出了差错,那么x的值就会出错。

例如:

  1. 线程A拷贝x副本到本地内存。
  2. 线程A对x的值+1,x的值为11。
  3. 线程B拷贝x副本到本地内存。
  4. 线程B对x的值-1,x的值为9。
  5. 线程A同步到主内存,主内存的x=11。
  6. 线程B同步到主内存,主内存的X=9。

####有序性
所以要保证同一时刻只有一个线程能操作数据。

Java引入了synchronized关键字将一段代码互斥,保证了线程访问数据的顺序。

1
2
3
synchronized(lock){  
some code...
}

如果synchronized关键字与static关键字同时用则锁对象为class对象,否则所对象为实例对象。