×

《线程系列》五、volatile

我的笔记 我的笔记 发表于2020-11-26 12:36:32 浏览3755 评论1

1人参与发表评论

上节的代码,让我们理解了主内存和工作内存的关系

接下来我们结合volatile来解决一些上节未解决的问题

volatile特性

1、强制将修改的值写入内存

2、当线程2修改变量值时,会导致线程1的工作内存的缓存失效

3、由于线程1的缓存变量失效,线程1会从主存再次读取



volatile是java中最轻量级的同步机制,当一个变量被volatile修饰后,它有两个特性:

可见性:保证变量对所有线程可见的,这里可见是指一个线程修改了值,这个修改对其他线程来说是立即可知的。

禁止指令重新排序优化:避免了多线程环境下程序出现乱序执行的现象


volatile原理和实现机制

加了volatile关键词,字节码文件会加一个lock关键词

lock指令实际上相当于一个内存屏障(也称内存栅栏),内存屏障提供三个功能:

1)、它确保指令重排时,不会把其后的指令排到屏障之前的位置,也不会把其前的指令放到屏障之后,即执行到内存屏障这句指令时,在它前边的操作已经完成。

2)、它会强制对缓存修改操作立即写入主存。

3)、如果是写操作,它会导致其他cpu中对应的缓存行失效。

volatile和synchronized来比,更加轻量级,因为它不会像synchronized一样阻塞,但是它不是什么场景都适合,volatile无法保证原子性,synchronized能保证三种特性,所以我们要具体情况具体分析。



代码上节问题:

package com.fyd;

public class JVMMOdelTest {
    public static void main(String[] args) {
        JVMModel jvmModel = new JVMModel();
        new Thread(jvmModel).start();
        while (true) {
            if (jvmModel.isFlag()) {
                System.out.println("------");
                break;
            }
        }
    }
}

class JVMModel implements Runnable {
    private volatile boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println(Thread.currentThread().getName() + ":" + flag);
    }

    public boolean isFlag() {
        return flag;
    }
}


我的笔记博客版权我的笔记博客版权