1、 什么是线程安全问题
我们使用多线程主要是为了提高应用程序的使用率,但同时会给我们带来很多线程安全问题。
多线程环境下,线程抢占CPU资源交替执行,一般他们会使用多个线程执行相同的代码。如果在这相同的代码里边有共享的变量,或者一些组合操作,我们想要正确的结果就很容易出现问题。
例如,我们模拟三个线程,同时去抢占资源,把资源类定义好的int count = 100,每执行一次减一,当count =0时,不再运行。
package com.atguigu.myself.safe;
public class CountInfo implements Runnable {
private int count = 100;
@Override
public void run() {
while (true) {
if (count > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"现在是"+count--);
} else {
break;
}
}
}
}
package com.atguigu.myself.safe;
public class SafeTest {
public static void main(String[] args) {
CountInfo countInfo = new CountInfo();
new Thread(countInfo).start();
new Thread(countInfo).start();
new Thread(countInfo).start();
}
}
运行测试类,会发现,有些count被打印执行了两次,甚至会出现count为-1的情况。
这里,count—是个复合操作,它会先读取count值,然后将count给代码中运行,最后再将count值-1。在多线程情况下,可能线程1读取到count值为1的时候,盘点count>0是满足的,
就进入if判断的逻辑中,但是此时线程2甚至线程3都获取道count为1,都进入道if判断的逻辑中,各自都给count-1。这就是一种线程安全问题。
2、 线程安全解决思路
一般采用下面几种方法来解决线程安全问题:
- 无状态,即没有共享变量;
- 使用final使共享变量不可变;
- 加锁;
- 使用JDK为我们提供的类来实现线程安全
- 其他;