【面试题】你知道Java内存模型中的原子性、有序性、可见性是什么吗?

本文探讨了Java并发编程中的三大问题:可见性、原子性和有序性。通过实例解释了如何使用volatile关键字解决这些问题,确保线程间数据的正确同步。volatile能防止指令重排序,确保更新对其他线程立即可见,并提供一定程度的原子性。理解这些概念对于编写高效、可靠的多线程Java代码至关重要。
摘要由CSDN通过智能技术生成

连环炮:Java内存模型--》原子性、可见性、有序性--》volatile--》happens-before/内存屏障

并发编程过程中,可能会产生的三类问题:

1.可见性

线程1 run代码:data++

线程2 run代码:while(data == 0){sleep(100);}

没有可见性:

一个线程已经更新了data,另外一个线程看不见

一个线程做data++操作,另外一个线程对data进行读取并判断操作。当线程1执行之前(1)到(6)操作,线程2已经获取到主内存中data的数据。在线程1将值写会主内存之前,他会一直循环等待

有可见性:

当线程1更新完data值时,强制要求线程2要重新从主内存中读取data的值,强制要求其他线程能看到当前的最新值

2.原子性

线程1在执行6道指令的时候,线程2不可以进行操作。可以保证同一时间只有一个线程可以对data进行++操作,保证两个线程同时更新时,不会出现最终data=1的情况

data++,必须是独立执行的,没有其他线程影响,当执行成功之后,其他线程才能进行下一次data++的操作

3.有序性

对于代码,同时还有存在指令重排序的问题。编译器和指令器有的时候为了提高代码执行效率,会将指令重排序

flag = false;
//线程1
prepare();//准备资源
flag = true;

//线程2
while(flag){
    Thread.sleep(1000);
}
execute();//基于准备好的资源执行操作

重排序后,让flag=true先执行了,会导致线程2直接跳过while等带,执行某段代码,结果prepare()方法还没有执行,资源还没有准备好,此时会导致代码逻辑出现异常

具备有序性,不会发生指令重排。不具备有序性,可能会发生指令重排,导致代码逻辑异常

指令重排演示

Class T{
    int m = 8;
}
T t  = new T();

对象创建过程

0	new #2<T>			            申请内存,初始化为0
4	invokespecial #3<T. <init>>	    变成8
7	astore_1			            建立堆栈的联系
8	return				            (半初始化过程)
                                    4、7互换即为指令重排序

半初始化过程:(1)有堆栈联系 (2)具有初始值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值