线程安全/线程安全保护机制/框架(spring)如何保证线程安全/线程安全编码实战
随着硬件软件的发展,cpu多核心,多线程随着而生,在很多的请求中,一个请求就是一个线程,我们无时无刻处于多线程之中,因此下面我就说说一些对多线程的自我理解
先理解一些名词吧,有利于后续的更深入理解
原子性:略
竞态条件:
当某个计算的正确性取决于多个线程的交替执行,那么存在竞态条件,数据竞争也是一种竞态,总之就是一段代码会被多线程执行的结果不可预测,那么存在竞态条件
复合操作:
当一个操作是需要原子性执行才能保证竞态条件不会发生,那个这样的操作就是一个复合操作,如i++(i是全局变量),他需要三个操作 读 ->赋值->写回,这三个操作在多线程下是竞态的,复合操作需要同步机制去保证数据安全
状态:
一个对象的可能出现的所有的可能性的集合,状态取决于可变全局对象,如类X有全局变量int a(1<=a<=2)和int b(1<=b<=2)
那么类 X至少有四种状态,因为a和b都有两种可能,那么组合起来就是四种,对象的状态取决于不确定的属性
可见性:
当一个值发生改变的时候,其他所有使用它的线程都会看到它的改变
发布溢出
当我们将一个全局变量被方法返回,导致每一个访问这个方法的线程都可以拿到这个全局变量,进而导致这个全局变量被多线程共同操作导致线程安全问题
如
public class A{
B b = new B();
public synchronized B getB(){
return b;
}
}
每个访问getB方法的人都可以拿到b对象,b对象溢出,多线程共享
线程封闭/栈封闭/ThresdLocal/实例封闭
这四个概念其实意思差不多,就是让变量只能在一个线程内进行活动,那么它就绝对是线程安全的,就像局部变量,它对于每个方法都是新的一份,所以不存在共享,也就不存啊并发
单例
有且只有一个,当然也不存在并发
不变性与final
对于static final的对象,因为不会改变,所以没有并发安全问题
二、在实际项目中,我们的每一个访问就是一个线程,多线程无处不在,项目中如何保证线程安全
以springboot为例子
1采用单例,然后注入,在单例模式的类里面不要出现全局变量,就不会有线程安全问题
2对于常量,直接声明为 private static final String/integer...
3尽量不声明全局变量
4大量采用局部变量(线程隔离)
5预防对象逃逸
6使用threadlocal
7必要的时候使用锁,或者并发包,