前言

不管是在面试还是实际开发中 volatile 都是一个应该掌握的技能。

首先来看看为什么会出现这个关键字。

内存可见性

由于 Java 内存模型(JMM)规定,所有的变量都存放在主内存中,而每个线程都有着自己的工作内存(高速缓存)。

线程在工作时,需要将主内存中的数据拷贝到工作内存中。这样对数据的任何操作都是基于工作内存(效率提高),并且不能直接操作主内存以及其他线程工作内存中的数据,之后再将更新之后的数据刷新到主内存中。

这里所提到的主内存可以简单认为是堆内存,而工作内存则可以认为是栈内存。

如下图所示:

volatile 关键字了解与使用

 

所以在并发运行时可能会出现线程 B 所读取到的数据是线程 A 更新之前的数据。

显然这肯定是会出问题的,因此 volatile 的作用出现了:

当一个变量被 volatile 修饰时,任何线程对它的写操作都会立即刷新到主内存中,并且会强制让缓存了该变量的线程中的数据清空,必须从主内存重新读取最新数据。

volatile 修饰之后并不是让线程直接从主内存中获取数据,依然需要将变量拷贝到工作内存中。

内存可见性的应用

当我们需要在两个线程间依据主内存通信时,通信的那个变量就必须的用 volatile 来修饰:

 1 public class Volatile implements Runnable{
 2 
 3 private static volatile boolean flag = true ;
 4 
 5 @Override
 6 public void run() {
 7 while (flag){
 8 }
 9 System.out.println(Thread.currentThread().getName() +"执行完毕");
10 }
11 
12 public static void main(String[] args) throws InterruptedException {
13 Volatile aVolatile = new Volatile();
14 new Thread(aVolatile,"thread A").start();
15 
16 
17 System.out.println("main 线程正在运行") ;
18 
19 Scanner sc = new Scanner(System.in);
20 while(sc.hasNext()){
21 String value = sc.next();
22 if(value.equals("1")){
23 
24 new Thread(new Runnable() {
25 @Override
26 public void run() {
27 aVolatile.stopThread();
28 }
29 }).start();
30 
31 break ;
32 }
33 }
34 
35 System.out.println("主线程退出了!");
36 
37 }
38 
39 private void stopThread(){
40 flag = false ;
41 }
42 
43 }
View Code

相关文章:

  • 2022-12-23
  • 2022-01-27
  • 2021-04-14
  • 2021-08-19
  • 2021-11-18
  • 2021-07-04
猜你喜欢
  • 2021-07-19
  • 2021-06-13
  • 2022-02-17
  • 2021-07-13
  • 2021-07-09
  • 2021-12-23
相关资源
相似解决方案