Volatile缓存可见性实现原理(JMM数据原子操作具体步骤)

Java内存模型:

在这里插入图片描述

JMM数据原子操作:

在这里插入图片描述

具体操作步骤:

在这里插入图片描述

线程1:先把initFlag变量read读取出来,再load载入工作内存,use使用线程1执行代码!initFlag

线程2:先把initFlag变量read读取出来,再load载入工作内存,use使用线程2执行代码initFlag=true,再assign重新赋值,store存储并写入主内存,write写入到主内存中的变量。(线程2对缓存行lock加锁,write写入主内存后会解锁unlock,防止initFlag还未write写入主内存就被线程1读取为false)。

线程1:因为initFlag被volatile修饰,使用MESI缓存一致性协议,线程1cpu总线嗅探机制监听到了initFlag值的修改,线程1中initFlag=false失效变为true退出循环继续执行,体现了多线程同步运行共享变量副本的可见性。如果initFlag没有被volatile修饰,线程1将感知不到initFlag的变化,一直循环下去停止不了。

图中的代码:

public class VolatileVisibilityTest {
    
    
    //volatile变量,用来确保将变量的更新操作通知到其他线程。
    private static volatile boolean initFlag = false;

    public static void main(String[] args) throws InterruptedException {
    
    
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("waiting data...");
                while (!initFlag) {
    
    

                }
                System.out.println("==============success");
            }
        }).start();

        Thread.sleep(2000);

        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                prepareData();
            }
        }).start();
    }
        public static void prepareData(){
    
    
            System.out.println("preparing data...");
            initFlag = true;
            System.out.println("prepare data end...");
        }
}

解决jmm缓存不一致问题:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


总线加锁:
lock和unlock会对主内存加锁的,总线加锁一般不使用,效率太低,跟单线程差不多。一般用MESI缓存一致性协议。
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41699562/article/details/104150671