java 并发 可见性_Java并发之原子性,可见性,有序性

原子性

​原子性指的是一个或者多个操作在 CPU 执行的过程中不被中断的特性

在多线程情况下,线程会被操作系统调度进行任务切换,占有CPU时间片段的就执行,否则就阻塞

2865e3ebdcc82e73e427ca4a16f06b68.png

java中对基础类型的变量赋值是原子性的,int  a = 1 ;

但是像这种语句 count++;在执行的时候,包含3的指令操作

指令 1:首先,需要把变量 count 从内存加载到 CPU的寄存器

指令 2:在寄存器中执行 +1 操作

指令 3:最后,将结果写入内存

在一个线程里执行是没有问题的,但是在多线程情况下,会引发数据不一致问题

对于上面的三条指令来说,如果线程 A 在指令 1 执行完后做线程切换,线程 A 和线程 B 按照下图的序列执行,那么我们会发现两个线程都执行了 count+=1 的操作,但是得到的结果不是我们期望的 2,而是 1。

e694e7cca49cd0351049043f289ae70b.png

可见性

可见性指的是当一个线程修改了共享变量后,其他线程能够立即得知这个修改,volatile可以保证可见性

5141b7cdaf1b212e11a3a3f98b9938af.png

有序性

​ 有序性指的是程序按照代码的先后顺序执行

为了性能优化,编译器和处理器会可能进行指令重排序,有时候会改变程序中语句的先后顺序

a = 5; //1

b = 20; //2

c = a + b; //3编译器优化后可能变成

b = 20; //1

a = 5; //2

c = a + b; //3

编译器调整了语句的顺序,在单线程中并没有什么影响,但是在多线程中可能会出现异常

单例模式有一种实现是

public classSingleton {staticSingleton instance;staticSingleton getInstance(){if (instance == null) {

synchronized(Singleton.class) {if (instance == null)

instance= newSingleton();

}

}returninstance;

}

}

我们先看 instance = new Singleton() 的未被编译器优化的操作

指令 1:分配一块内存 M;

指令 2:在内存 M 上初始化 Singleton 对象;

指令 3:然后 M 的地址赋值给 instance 变量。

编译器优化后的操作指令

指令 1:分配一块内存 M;

指令 2:将 M 的地址赋值给 instance 变量;

指令 3:然后在内存 M 上初始化 Singleton 对象。

现在有A,B两个线程,我们假设线程A先执行getInstance()方法,当执行编译器优化后的操作指令2时(此时候未完成对象的初始化),这时候发生了线程切换,那么线程B进入,刚好执行到第一次判断instance == null 会发现instance

不等于null了,所以直接返回instance,而此时instance是没有初始化的

d81bc988b5f988420226269bc62ab8ff.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值