Skip to content

Latest commit

 

History

History

线程安全

什么是线程安全?

当多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替运行,
也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,
调用这个对象的行为都可以获取正确的结果,那这个对象是线程安全的。(摘自《深入Java虚拟机》)

如何保证线程安全

  • 无状态
就是线程只有入参和局部变量,如果变量是引用的话,确保变量的创建和调用生命周期都发生在线程栈内,就可以确保线程安全。
  • 无共享状态 (线程封闭)
完全要求线程无状态比较难实现,必要的状态是无法避免的,那么就必须维护不同线程之间的不同状态。
ThreadLocal 结构跟当前线程绑定,而且只对当前线程可见,完美解决了无共享状态的问题。
  • 不可变状态
最后实在没办法避免状态共享,在线程之间共享状态,
最怕的就是无法确保能维护好正确的读写顺序,而且多线程确实也无法正确维护好这个共享变量。
那么我们索性粗暴点,把共享的状态定位不可变,比如价格final修饰一下,这样就达到安全状态共享。
  • 消息传递
一个线程通常也不是所有步骤都需要共享状态,而是部分环节才需要的,那么我们把共享状态的代码拆开,
无共享状态的那部分自然不用关心,而共享状态的小段代码,则通过加入消息组件来传递状态。
这个设计到并发模式的流水线编程模式。
  • 线程安全容器
JUC里面提供大量的并发容器,涉及到线程交互的时候,使用安全容器可以避免大部分的错误,而且大大降低了代码的复杂度。
该关键字确保代码块同一时间只被一个线程执行,在这个前提下再设计符合线程安全的逻辑。
  • volatile 约束
volatile确保每次操作都能强制同步CPU缓存和主存直接的变量。而且在编译期间能阻止指令重排。
读写并发情况下volatile也不能确保线程安全。