3.3 线程安全
线程安全是指当我们多个线程去同时去执行我们写的同一段代码不会发生安全问题,这就是线程安全。线程安全意味着代码有效的处理了资源竞争的问题(Race condition),在并发的情况下对与资源的处理不会发生错误或者得到非预期结果。
3.3.1 线程不安全
什么情况下会发生线程安全问题呢?请看下例。
/**
* Copyright(c)lbhbinhao@163.com
* @author liubinhao
* @date 2021/1/30
* ++++ ______ ______ ______
* +++/ /| / /| / /|
* +/_____/ | /_____/ | /_____/ |
* | | | | | | | | |
* | | | | | |________| | |
* | | | | | / | | |
* | | | | |/___________| | |
* | | |___________________ | |____________| | |
* | | / / | | | | | | |
* | |/ _________________/ / | | / | | /
* |_________________________|/b |_____|/ |_____|/
*/
public class ThreadUnSafe implements Runnable {
private int count;
@Override
public void run() {
count++;
}
public static void main(String[] args) {
ThreadUnSafe threadUnSafe = new ThreadUnSafe();
for (int i=0;i<100;i++){
new Thread(threadUnSafe).start();
}
System.err.println("the final count:"+ threadUnSafe.count);
}
}
上述代码例子中,我们并没有得到我们预期的结果100,这说明了多线程去执行我们代码的时候发生了并发问题,导致了最后的结果不符合预期,多线程安全问题就发生了,那应该怎样解决线程安全问题呢?
3.3.1 线程安全问题解决思路
a. 排查线程安全问题,使用线程控制逃逸规则(Thread Control Escape Rule):当一个资源创建了(如一个文件或者数据记录对象实例),看该资源是否只在创建它的线程的控制下,如果是则不会出现线程安全问题,如果不是,则可能发生资源竞争,需要注意线程安全问题。
b. 处理并发问题,通过并发控制技术来确保多线程同时执行我们的代码的时候不会产生非预期结果(技术手段如JUC,Atomic,串行等等)。
3.3.1 不可变(Imutable)
上述可知只有当一个资源被多线程同时操作是才会发生资源竞争(Race Condition),而不是同一个资源则不发生资源竞争,对于不可变的对象则用法不会发生线程安全问题,因为其是不可变的,那么是什么是不可变对象呢?
class Imutable{
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Imutable add(){
Imutable imutable = new Imutable();
imutable.setCount(++count);
return imutable;
}
}
不可变即不可以对其类实例进行修改的对象,如果有对其修改的操作是另一个对象。注意一个实例的操作是线程安全的,但是对其引用不一定是线程安全。