提示(点击跳转)
2.1 什么是线程安全?
2.2 原子性
2.2.1 竞态条件
2.2.2 延迟初始化中的竟态条件
2.2.3 复合操作
2.3 加锁机制
2.3.1 内置锁
2.3.2 重入
2.4用锁来保护状态
2.5 活跃性与性能
Java中主要的同步机制有关键字synchronized,volatile变量,显示锁,原子变量。
2.1 什么是线程安全?
- 线程安全就是当多个线程访问某个类时,这个类始终都能表现出正确的行为。
- 下面代码展示了无状态对象(类),应为里面没有可变的变量或状态。所以一定是线程安全的。
/**
*因为访问此方法,不会影响另一个线程对其访问计算的结果,所以线程安全。
* 也就是多个线程去访问此方法结果是不互相干扰的,没有共享的变量。
* 它不包含共享的变量和其他域中的引用,计算过程中临时状态仅存在线程栈上的局部变量中。
*/
@ThreadSafe
public class StatelessFactorizer implements Servlet {
public void service(ServletRequest req, ServletResponse resp){
BigInteger i = extractFromRequest(req);//获取数
BigInteger[] factors = factor(i);//对servlet中数进行因数分解
encodeIntResponse(resp,factors);//将因数进行返回
}
}
2.2 原子性
所谓的原子性,要不都一次执行,别的线程不能干扰,要不都不执行。
/**
* 统计已处理请求的个数
* 这个为线程不安全。假设count的初始值为5,当来多个线程去执行service的时候,都将其值改为了6,这就造成了
* 严重错误。
*/
@NotThreadSafe
public class UnsafeCountingFactorizer implements Servlet {
private long count = 0;
public long getCount(){
return count;
}
public void service(ServletRequest req, ServletResponse resp){
BigInteger i = extractRequest(req);
BigInteger[] factors = factors(i);
++count;
encodeIntResponse(resp,factors);
}
}
上面代码分析原因:
在这个类中有了共享变量count,同时++count的操作不是原子性的,有三个独立的操作在进行“读入-修改-写入”的操作序列,并且最终结果依赖于之前count的状态。n(n>2)个线程到来都进行读入count之前状态,然