java内存屏障

本文详细解释了内存屏障如何解决线程可见性和有序性问题,以及ReentrantLock利用volatile变量保证锁操作后数据同步的机制。通过测试类展示了volatile变量如何影响共享变量的更新和读取。

参考:https://blog.youkuaiyun.com/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变量改变之前的所有共享变量的改变都会刷新到主内存

volatile读写内代码可以重排序,和synchronized同步内的代码一样都可以重排序

一个自己写的测试类

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();
    }



}

volatile用在一个对象上时,禁止对象的创建重排序,还有对象的引用发生变化另一个线程立即可见。

synchronized和volatile类似的功能

synchronized可见性:或Lock接口进行同步时,获取锁时,会从主内存读取最新数据;在释放锁之前,会将修改的数据刷新到主内存中。

synchronized重排序:synchronized内的代码禁止溢出{},但同步内的代码可以重排序

在一个方法内如果有2个方法,这2个方法会被重排序吗?

编译器通常不会重排序这两个方法调用,因为它们是独立的语句,并且依赖于方法的调用顺序。编译器优化主要关注于单个方法内部的操作,而不是跨方法的调用顺序。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值