栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

浅谈volatile

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

浅谈volatile

前言

提到volatile关键字的原理,我这里不想赘述,其实我也讲不好,因为这不是一篇简短的文章和我这个水平就能讲的清楚的,我建议你如果想了解一下volatile的原理,可以去看一下《Java并发编程的艺术》这本书中的2-1,3-4章节,认真通读一遍,你就会了解volatile设计到了哪些cpu指令,是如何保证的共享变量的可见性,以及使用volatile来进行线程之间通信的原理,volatile关键字相较于synchronized的优势等等,相信你会有所收获。

volatile

这篇文章我主要和大家分享几个我当初学习volatile时比较疑惑的问题

volatile一写多读是线程安全的,多写多读是线程不安全的,为什么。

可能大家在很多博客里都看到过这么一句话,有的博客可能就一笔带过。今天我来分享一下这个问题。在这个问题之前,我们来明确几条定义:
每个线程都有自己的变量副本,变量的读写就是对自己线程变量副本的读写
对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
可以简单理解为,一个volatile变量的读,总是会读取主内存变量的最新值
一个volatile变量的写,总是会把变量刷新到主内存

  1. 我们先来讨论一写一读,一个线程A修改变量之后,另一个线程B去读取变量。按照上面的定义,是可以读到线程A修改后的值,这个没问题
  2. 一写多读,其实和一写一读是一样的。每一个读取线程都可以拿到写线程最后修改的值
  3. 多写多读,如果是对单个volatile变量的读或者写,其实仍是线程安全的。出现线程不安全的地方是类似volatile++这种非原子性操作。举个例子,有一个共享变量 volatile a = 1;线程A和线程B分别对变量a执行a++操作。++操作不是一个原子操作,可以分解为三步:
		int temp = a; // 第一步
        temp = temp + 1; // 第二步
        a = temp; // 第三步

线程A执行++操作,在执行完第二步的时候,线程A的本地副本变量里,a = 1;temp = 2;
此时线程A交出时间片,线程B执行++操作,执行完毕把a的值修改成了2,由于变量a是volatile变量,线程B把a=2同步到主内存。线程A继续执行,此时会刷新自己变量副本的变量a值,此时线程A的本地副本变量里,a = 2;temp = 2, 继续执行第三步,就变成了2 = 2;执行完毕把变量a刷回主内存,此时变量a还是2,不是预期的3。
这里我简单写个demo模拟了一下

public class Demo {
    private volatile int num;

    public void add() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        try {
            for (int i = 0; i < 1000; i++) {
                executorService.execute(() -> num++);
            }
            System.out.println("num的值:" + num);
        } finally {
            executorService.shutdown();
        }
    }

    public static void main(String[] args) {
        Demo1 demo1 = new Demo1();
        demo1.add();
    }
}

运行结果,运行5次,发现都不一样。

num的值:972
num的值:990
num的值:984
num的值:983
num的值:985
如何解决这个问题

可以用cas来解决这个问题。比如上面那个问题,如果线程A在最后更新副本变量a的时候,使用cas来判断一下旧的值是否符合我们的预期,也就是说变量a是不是等于1,发现不等于1了,重新执行++操作,最后变量a的结果就是正确的3。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/490685.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号