java内存可见性

什么是可见性

一个线程对共享变量值的修改,对其他线程而言也能被及时的看到

 

共享变量

如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这个几个线程的共享变量。

 

主内存:保存了程序的所有变量。

 

工作内存:每个线程都有自己的独立工作内存,里面保存了该线程使用的变量的副本(主内存对该变量的一份拷贝)

 

Java内存模型(JMM)

描述了java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。

主内存被三个线程共享,每个线程都有自己的工作内存,多个线程负责与自己工作内存交互也负责与主内存交互,线程不能与主内存直接进行交互,共享变量x都被3个线程使用,所以在3个线程中都使用了这个变量

 

Java中规定了:

1.线程对共享变量的所有操作都必须从自己的工作内存中读写不能直接从主内存中读写。

2.不同线程之间不能直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。

 

共享变量实现可见性的原理 以及如何保证变量的可见性

若线程1对共享变量的修改需要被线程2看到,那么就需要将:

1.把工作内存1中更新过的变量刷新到主内存中去

2.将主内存中最新的变量更新到工作内存2中。

 

总之,要实现共享变量的可见性,必须要保证2点:

1.线程修改后的共享变量值必须及时从工作内存刷新到主内存

2.其他线程能及时的把共享变量的最新值从主内存中更新到自己的工作内存中。

 

实现可见性的方式

1.synchronized

2.volatile

 

synchronized2条规定

1.线程解锁前(退出synchronized代码块前),必须将共享变量的最新值刷到主内存中。

2.线程加锁时,将清空工作内存中共享变量的值,以便及时从主内存读取最新的值(解锁和和加锁时相同的一把锁)。

线程解锁前对共享变量的修改在下次加锁时对其他线程可见。

 

导致共享变量在线程之间不么见的原因:

1.线程的交叉执行 —— synchronized 原子性

2.重排序结合线程交叉执行 —— synchronized 原子性

3.共享变量更新后的值没有在工作内存与主内存之间及时刷新 —— synchronized 可见性

 

线程写volatile的过程

1.改变线程工作内存中volatile修饰的变量副本的值

2.将工作内存中改变的值刷到主内存

 

线程读volatile的过程:

1.从主内存中读取volatile变量的最新值到线程的工作内存中

2.从工作内存中读取volatile变量的副本

 

volatile的使用场合

1.对变量的写入操作不依赖其当前值:

不满足count++、count = count *5;

满足boolean变量等;

 

线程执行互斥代码的过程:

1.获得互斥锁

2.清空自己的工作内存

3.从主内存中拷贝最新的副本到工作内存

4.执行代码

5.将更改后的变量的值刷新到主内存

6.释放互斥锁

猜你喜欢

转载自www.cnblogs.com/wanghy898/p/10907478.html