什么是线程安全?
当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么这个类就是线程安全的。状态变量出现线程不安全的解决办法?
① 在访问状态变量时使用同步
②将状态变量修改为不可变的变 的变量
③不在线程之间共享该变量竞态条件的产生导致的线程不安全
- 3.1 竞态条件(Race Condition):计算正确性取决于 多线程交替执行的时序时,就会产生竞态条件。
-
3.2 竞态条件产生线程安全的示例:
- 示例一: 在没有线程同步的情况下统计已处理请求数量的Servlet
public class UnsafeCountingFactory implements Servlet{
private long count;
public long getCount(){return count;}
public void service(ServletRequest req,ServletResponse resp){
++count;
}
}
- 当线程在执行++count时,实际上包含三个独立的操作:读取count的当前值,将其加1,然后将计算结果返回给count.这是一个 “读取-修改-写入”的操作时列,其结果状态依赖于之前线程操作的状态。所以当线程A,B执行结果可能会出现以下糟糕的情况:
- 示例二:延迟初始化问题
public class LazyInitRace{
private ExpensiveObject instance=null;
public ExpensiveObject getInstance(){
if(instance==null)
instance=new ExpensiveObject();
return instance;
}
}
- 在LazyInitRace 中假定线程A和线程B同时执行getInstacance()。A看到instance为空,进入if条件语句,而此时线程B也执行到if条件语句,判断instance 同样为空,也进入if条件语句。因而线程A和线程B各自创建了一个创建一个新的ExpensiveObject实例,导致两次调用getInstance()得到不同的结果。