zoukankan      html  css  js  c++  java
  • 关于Java中volatile关键字笔记

    volatile通常被认为是一种轻量级的synchronized,字面上它表示易变的,在并发编程中,它保证了共享变量的可见性。所谓可见性指的是,某个线程对变量进行操作后,其他线程能够读取到操作后的最新结果。

    CPU通常不会直接与内存通信,内存中的数据首先会被读取到缓存中进行读写。当对声明了volatile的变量进行写操作时,JVM会向处理器发送一条Lock前缀的指令,表示将变量锁在的缓存行数据写回内存中。

    当写一个volatile变量时,Java内存模型JMM会把线程对应的本地内存的共享变量刷新到主内存中

    然而volatile并不能保证线程安全,来看下面的例子

    public class VolatileTest {
        private static volatile Integer num = 0;
    
        public static void main(String[] args) throws InterruptedException {
            Thread[] threads = new Thread[10];
            for (int i = 0; i < 10; i++) {
                threads[i] = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int k = 0; k < 10000; k++) {
                            num++;
                        }
                    }
                });
                threads[i].start();
            }
            for (int i = 0; i < 10; i++) {
                threads[i].join();
            }
            System.out.println(num);
        }
    }

    这一段代码的期望运行结果应当是输出100000,然而实际测试发现是一个小于100000的数字,说明voilatile不能保证++操作的原子性。

     volatile关键字修饰的变量被读或者被写是使用锁来同步,并且对于volatile修饰变量的读总是可以读到任意线程对这个变量(当时)最新的写入。但是对于读并且写这样的复合操作是不具有原子性的。

    volatile关键字修饰的变量具有对其写happens-before对其读的规则,因此线程总能看见任意线程对此volatile变量最新的修改。

    volatile变量具有的特性如下

    可见性:总是能够读到任意线程对volatile变量最新的修改

    原子性:对单个volatile变量的读或者写具有原子性,但复合操作如++不具有原子性

  • 相关阅读:
    【线程间通信:代码示例:分析问题原因:修正代码】
    【死锁问题】
    【解决线程安全问题:通过Lock锁对象】
    【解决线程安全问题:同步方法】
    【解决线程安全问题:同步代码块】
    【线程实现的两种方式及区别】
    小阳的贝壳
    小石的妹子
    SPFA模板+dfs版检测负环
    逆序对模板
  • 原文地址:https://www.cnblogs.com/micrari/p/5627450.html
Copyright © 2011-2022 走看看