JavaEE 线程安全
JavaEE 线程安全近来重新开始复习多线程的知识,故此将线程安全这块重点单拎出来做文章记录,方便后续回想
1. 概念
什么是线程安全题目?很直观的说,就是一段代码,在单线程的环境下没有题目,但是在多线程的环境下却出现了题目,我们则可称这段代码存在线程安全题目。
我们用代码举例:
我如今有两个线程,我希望通过这两个线程来对一个变量count举行加法运算,每个线程各加50_0000,末了在主线程输出count
代码如下:
public class Test1 {
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 1;i <= 500000;i++) {
count++;
}
});
Thread t2 = new Thread(() -> {
for (int i = 1;i <= 500000;i++) {
count++;
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("count = " + count);
}
}
正常在单线程环境下,举行上述的代码操纵,末了得到的count会等于100_0000,但是在多线程的环境下,上述操纵得到的结果却不是我们所意推测的结果:
https://i-blog.csdnimg.cn/direct/0a4bc0b5b53b453385e332110527e366.png#pic_center
为什么相差这么多?且每次运行的结果都不一样!
根本原因便是线程之间的调度是无序的,随机调度的,也称抢占式执行
正因如此,在上述代码中,两个线程对count这个对象的修改操纵会产生很多种情况:
注:count++这个操纵本质上是由三条CPU指令构成的:
[*]load:把内存中的数据加载到寄存器中;
[*]add:将寄存器中的数据举行加1运算;
[*]save:将寄存器中的数据写回到内存中;
合理的情况:
https://i-blog.csdnimg.cn/direct/1f792ad202f7435bbaa7d2d0cccb5e66.png#pic_center
不合理的情况:
https://i-blog.csdnimg.cn/direct/331799e2f6b54585b0061f085e2a2756.png#pic_center
上述的不合理情况还有多种,这里举最典型的情况,如上图,可以看到在多线程的环境下,线程的随机调度导致无法保证操纵的原子性,导致t1线程值还没修改完,t2线程就对count举行了修改,末了仍旧被t1线程修改后的旧值所覆盖,这也是我们上述代码得到结果不准确且不唯一的原因!
对此也得出一个结论:导致线程安全题目标根本原因是线程的随机调度,同时在代码结构上也与多个线程同时对同一个对象举行修改有关;
那么既然题目出现了,我们就要想办法解决它!
2. 如何解决线程安全题目
对于线程安全题目,我们常规的解决方案便是-加锁
页:
[1]