一篇文章带你了解并发编程的核心问题以及实战场景


前言

从并发编程中的原子性、可见性、有序性三个角度出发,最后结合单例模式的双重校验锁模式进一步分析volatile的实战场景。


一、并发编程核心问题

并发编程的核心问题就是解决三个特性:可见性、有序性、原子性。

什么是可见性?
一个线程对共享变量的修改,另外一个线程能够立刻看到,我们称为可见性

什么是有序性?
有序性指的是程序按照代码的先后顺序执行
注意:编译器和处理器可能会对指令进行重排序,会影响到多线程并发执行的正确性.

什么是原子性?
操作是不可再分割的。

例如:int i=0   就是一条原子性操作。

为什么i++不是线程安全的? 因为i++不是一个原子性操作。
例如:i++ ,需要三条指令
(1)把变量i从内存加载到工作内存;
(2)在工作内存执行 +1 操作;
(3)将结果写入内存;

在多线程环境下,两个线程各自执行100次i++操作,i的值为多少?
答:i的取值范围可能是[2,200]之间。取值为200很容易理解,这是我们希望看到的状况。但为什么会出现取值为2的情况?

i刚开始为0时,两个线程的状态如下:线程A和线程B的工作内存的i的值都为0
在这里插入图片描述
1.线程A执行了99次操作,把i加到了99,然后写入了主内存,但是线程B的工作内存值还是为0,随后线程B进行了一次i++操作,把i修改成了1写入了主内存,这样线程B的i值就覆盖了线程A的值。

2.然后线程A读取主内存的值为1,线程B也读取主内存的值为1,线程B进行了99次操作,把i加到了100写入主内存,线程A执行了最后一次+1操作,把i=2写入了主内存,覆盖了主内存的100,所以最后i的值为2。


二、解决思路

原子性:考虑atomic包下的类。
可见性和有序性:考虑volatile关键字。

注意:,volatile关键字是无法保证原子性,使用synchronize能保证原子性和可见性以及有序性:因为只有一个线程能获取到synchronize锁,当然不会出现并发修改问题,但是效率太低,建议不要一上来就使用sychonize。

在这里插入图片描述


三、双重校验锁

双重校验锁是单例模式的一种实现方法,之前的文章中已经介绍了,但为详细解释为什么要使用volatile关键字修饰单例对象。首先我们来回顾一下双重校验锁的实现代码。

public class LockSingleton {
    private  volatile static LockSingleton lockSingleton;
    private LockSingleton(){}
    public static LockSingleton getInstance(){
        if(lockSingleton==null){
            synchronized (LockSingleton.class){
                if (lockSingleton==null){
                    lockSingleton=new LockSingleton();
                }
            }
        }
        return lockSingleton;
    }
}

创建一个对象实例lockSingleton=new LockSingleton(),可以分为三步:
1.分配对象内存
2.调用构造器方法,执行初始化
3.将对象引用赋值给变量。

虚拟机实际运行时,以上指令可能发生重排序。以上代码 2,3 可能发生重排序,重排序并不影响单线程内的执行结果,但是在多线程的环境就带来一些问题。
在这里插入图片描述
例如:线程1准备创建单例对象,但发生了重排序,没有初始化对象就直接把对象赋值给了单例变量lockSingleton,此时线程2准备访问lockSingleton,由于lockSingleton不是null,直接返回使用,但未进行初始化,访问可能会出现问题。

正确的双重检查锁定模式需要需要使用volatile
1.保证可见性。使用 volatile定义的变量,将会保证对所有线程的可见性。
2.禁止指令重排序优化,由于 volatile禁止对象创建时指令之间重排序,所以其他线程不会访问到一个未初始化的对象,从而保证安全性。


总结

本章内容介绍了并发编程核心问题以及具体的解决思路,并结合设计模式的内容列出了volatile关键字的实战场景,有助于加深理解。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JinziH Never Give Up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值