0
点赞
收藏
分享

微信扫一扫

【多线程&高并发】深入浅出原子性


1.首先如何理解原子性这个概念?

【多线程&高并发】深入浅出原子性_i++

想必都学过化学,在该化学反应中“原子”被称为不可再分割的微粒,而我们并发编程中的“原子性”与该概念类似,指的是某一个操作能否在一个CPU时间段内完成。(要么把该操作相关的指令全都执行完,要不执行

📑能完成最好,那当然不会出现什么问题!
📑如果不能完成,那就可能产生一些问题了

【会发生什么问题呢?】

【多线程&高并发】深入浅出原子性_i++_02


首先得考虑清除什么情况下会发生原子性问题,单线程会嘛?当然不会,你一个线程又不发生线程切换,就不需要保证操作得原子性。

【多线程&高并发】深入浅出原子性_java_03


所以说,只有在多线程环境下,才会出现原子性问题。

看下面代码,使用5个线程各自对a进行1000次的++操作。

public class Atomicity {

private static int a = 0;
public static void main(String[] args) throws InterruptedException {
Runnable increment = () -> {
for (int i = 0; i < 1000; i++) {
a++;
}
};
for (int i = 0; i < 5; i++) {
Thread t = new Thread(increment);
t.start();
}
TimeUnit.SECONDS.sleep(2);
System.out.println(a);
}
}

想必都能猜出结果:

结果有可能是5000也有可能低于5000.

2.从字节码角度分析++操作

public class AddOperation {
private static int num = 0;

public void method() {
num++;
}
}

对上述代码进行反汇编,结果如下:

【多线程&高并发】深入浅出原子性_java_04

getstatic:将类变量num的值取出将其压入操作数栈
iconst_1:将常数1压入操作数栈
iadd:执行一次加法操作(连续弹栈两次,将整型数据相加,并将结果压入操作数栈)
putstatic:将栈顶数据弹出,赋给num

当两个线程对num进行++操作时,会发生什么现象呢?

【多线程&高并发】深入浅出原子性_原子性_05

【多线程&高并发】深入浅出原子性_多线程_06


这就是产生了原子性问题。如何解决呢?(只演示synchronized)

Runnable increment = () -> {
synchronized (lock) {
for (int i = 0; i < 1000; i++) {
a++;
}
}
};

【多线程&高并发】深入浅出原子性_高并发_07


举报

相关推荐

0 条评论