并发编程中原子性,有序性,可见性

原子性:

一个或多个指令在CPU执行过程中不允许中断的。
之前文章,在汇编层面证明,i++不是原子操作:
https://blog.csdn.net/weixin_41905047/article/details/129542913
可以通过加锁实现操作的原子性,java中加锁有两种形式,通过synchronized关键字,lock锁。

有序性:

概念:指令在CPU调度执行时,CPU会为了提升执行效率,在不影响结果的前提下(满足happens-before原则),对CPU指令进行重新排序。
解决方案:如何避免指令重排,对应的属性用volatile修饰,就不会进行指令重排。
使用场景:单例模式DCL双重判断

public class Single {


    private volatile static Single single;

    private Single() {
    }

    public static Single getInstance() {
        
        if (null == single) {
            synchronized (Single.class) {

                /**
                 * 加volatile的原因,避免下面的情况:
                 * 创建对象会经历:申请内存,初始化,关联是正常顺序,如果CPU对指令重排,可能会造成
                 * 申请内存,关联,初始化,在还没有初始化时,其他线程来获取数据,
                 * 导致获取到的数据虽然有地址引用,但是内部的数据还没初始化,都是默认值,
                 * 导致使用时,可能出现与预期不符的结果
                 */
                if (null == single) {
                    single = new Single();
                }
            }
        }

        return single;
    }
}

可见性:

概念:
CPU在处理时,需要将主内存数据同步到寄存机中再执行指令,执行完指令后,需要将寄存器数据扔回到主内存中,但是寄存器数据同步到主内存是遵循MESI协议的,换句话说,不是每次操作结束就将CPU缓存数据同步到主内存,造成多个线程看到的数据不一样。
解决方案:
使用volatile或者synchronized,操作后都会同步数据到主内存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值