线程安全性
1.什么是线程安全性
...可以在多个线程中调用,并且在线程之间不会出现错误交互。
...可以同时被多个线程调用,而调用者无需执行额外的动作。
对于线程安全性,最核心的概念就是正确性。那什么是正确性呢,可以理解为某个类的行为与其规范完全一致。当多个线程访问某个类时,这个类始终能表现出正确的行为,那么就称这个类是线程安全的。
单线程也可以看成是一个多线程程序,所以说某个类在单线程中都不是正确的,那它肯定不是线程安全的。
2.原子性
2.1竞态条件
当某个计算的正确性取决于多个线程的交替执行时序时,那么就会发生竞态条件。换句话说,就是正确的结果取决于运气。最常见的竞态条件类型就是“先检查后执行(Check-Then_Act)”操作。即通过一个可能失效的观测结果来决定下一步的动作。
例如:你中午计划在A地的星巴克与一位朋友见面。但是当你到达那里时,发现A地有两家星巴克,并且不知道是在哪家星巴克碰面。在12:00时,你没有在星巴克A看到你的朋友,那么就会去星巴克B看看他是否在那里,但他也不在那里。那么有几种可能:①你的朋友迟到了,还没有到任何一家星巴克。②你的朋友在你离开后到了星巴克A。③你的朋友在星巴克B,但他去星巴克A找你,并且此时正在去星巴克A的途中。假设是最糟糕的情况,即第三种,你们两个都去了两家星巴克,但是都没有见到对方,都开始怀疑对方是否失约了。两家星巴克之间有几分钟的路程,就在这几分钟的时间里,系统状态可能会发生变化。
2.2复合操作
要避免竟态条件问题,就必须在某个线程修改该变量时,通过某种方式防止其他线程使用这个变量,从而确保其他线程只能在修改操作完成之前或之后读取和修改状态,而不是在修改状态过程中。
在实际情况中,应尽可能地使用现有的线程安全对象(例如AcomicLong)来管理类的状态。与非线程安全的类相比,判断线程安全的可能状态及其状态转换情况要更为容易,从而也更容易维护和验证线程安全性。