由于线程调度是随机的,这样可能会产生一些bug,导致了线程不安全。
1. 一个线程不安全的典型案例
使用两个线程,对同一个变量,进行自增操作,每个线程自增5W次,看最终结果。
//两个线程对同一个变量,各自自增5W次 class Counter{ public int count; public void increase(){ count++; } } public class Demo05 { private static Counter c = new Counter(); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(()->{ for (int i = 0; i < 50000; i++) { c.increase(); } }); Thread t2 = new Thread(()->{ for (int i = 0; i < 50000; i++) { c.increase(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(c.count); } } 65075 Process finished with exit code 0
分析:
count++ 执行过程
1)将内存中的count值加载到CPU寄存器中 load
2)把寄存器中的值加1 add
3)将寄存器中的值写回到内存count中的 save
在两个线程抢占式执行的情况下,上面的三个指令执行的顺序充满了随机性~
解决方法:在自增之前先加锁 lock , 在自增之后再解锁unlock