java内存屏障

2024-01-07 19:46:31

参考:https://blog.csdn.net/weixin_73077810/article/details/132804522

内存屏障主要用于解决线程的可见性有序性问题

代码案例:

ReentrantLock保证可见性的原理
? ? ? ? 在 lock.lock() 和 lock.unlock() 时,都会操作 AbstractQueuedSynchronizer类 中的一个变量 state,这个变量是 volatile 修饰的,volatile变量的语句对应的汇编码指令中会多加一行lock addl $0x0, (%esp),这一行的作用是:

(1)将工作内存修改了的缓存(不仅仅是该变量的缓存)都强制刷新回主内存

(2)把其他CPU对应缓存行标记为invalid状态,那么在读取这一部分缓存时,必须回主内存读取。这样也就保证了线程间的可见性

? ? ? ? 具体来说,当一个线程获取ReentrantLock锁时(state值改变),它会将主内存中的数据刷新到自己的工作内存中state值改变之后的所有对共享变量的读操作)。而当一个线程释放ReentrantLock锁时(state值改变),它会将自己工作内存中的数据刷新到主内存中(state值改变之前的所有对共享变量的写操作),这样其他线程就能够读取到最新的值。

备注:

volatile变量改变之后所有的共享变量读操作都会从主内存中重新获取最新值到工作内存,volatile变量改变之前的所有共享变量的改变都会刷新到主内存

一个自己写的测试类

import org.junit.jupiter.api.Test;

import java.util.concurrent.TimeUnit;
class TestCache {

    private volatile  Boolean r=false;
    private String string="1";


    Thread readThread=null;
    Thread writeThread=null;

    /**
     *
     */
    @Test
    void contextLoads() throws InterruptedException {
        readThread=new Thread(()->{
            while (true){
//下面的这2个if顺序说明了:volatile后的共享变量重新获取了,之前的不再重新获取
//                if( r && string.contentEquals("2")  ){//能看到string的变化
                if(  string.contentEquals("2") && r  ){//不能看到string的变化
                    System.out.println("end task");
                    break;
                }
            }

        });
        writeThread=new Thread(()->{
            string="2";
            r=true;
        });

        readThread.start();
        TimeUnit.SECONDS.sleep(2);

        writeThread.start();
        readThread.join();
    }



}

文章来源:https://blog.csdn.net/wangbingqi/article/details/135437120
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。