码迷,mamicode.com
首页 > 编程语言 > 详细

Volatile关键字回顾之线程可见性

时间:2020-03-22 19:39:57      阅读:72      评论:0      收藏:0      [点我收藏+]

标签:工作   线程   可见   public   div   ack   ace   失效   数据   

java中,volatile关键字有两大作用:

  1.保证线程的可见性

  2.防止指令重排序

这篇文章主要通过典型案例,体现可见性这一特性。

概念:

  java中,堆内存是线程共享的。而每个线程,都应该有自己独享的内存用于工作。所以,当线程访问到堆内存中的共享变量时,会考虑copy一份,存在自己的工作空间中。之后对工作空间中的值进行操作,完成后重新写回到堆内存。

  这样一来,在多线程同时访问这个变量时,就可能出现拿不到实时的值的问题(根本原因在于:本来共享的变量,因为缓存到各个线程的工作空间导致数据在写回之前不互通)。

  而volatile的作用之一,就是解决这一问题。

下面通过一段代码,来展示volatile的这一特性。

 1 public class HelloVolatile {
 2     private volatile boolean running = true; //开关,表示是否可运行
 3 
 4     void m(){
 5         System.out.println("m start");
 6         //一直执行
 7         while(running){
 8 
 9         }
10         //如果running一直未true,下面的代码执行不到
11         System.out.println("m end");
12     }
13 
14     public static void main(String[] args) {
15         HelloVolatile helloVolatile = new HelloVolatile();
16         //新建线程,run方法调用m方法,running为true时一直循环
17         new Thread(helloVolatile::m, "非主线程").start();
18         //休眠1s
19         try {
20             TimeUnit.SECONDS.sleep(2);
21         } catch (InterruptedException e) {
22             e.printStackTrace();
23         }
24         //主线程设置running为false,如果running不加volatile,则新建的线程是读不到的
25         helloVolatile.running = false;
26     }
27 }

running变量不加volatile的执行结果:

m start

加了volatile的执行结果:

m start
m end

可见性的原理:

MESI(缓存一致性)协议:

  1.写数据时,如果发现操作的是共享变量,会发出信号通知其他CPU设置该变量的缓存行为无效状态。

  2.当其他CPU使用这个变量时,会先去观察是否有更改的信号,当发现缓存行失效时,会从主内存(堆中)重新读取此变量。
volatile的优缺点:

  优点:高效(非锁机制)

  缺点:仅仅保证可见性,不保证数据的一致性。

Volatile关键字回顾之线程可见性

标签:工作   线程   可见   public   div   ack   ace   失效   数据   

原文地址:https://www.cnblogs.com/nysd/p/12547703.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!