作者:Brian Goetz
本书结构:
简要的介绍:第1章
基础知识:第一部分(第 2 章 ~ 第 5 章)
结构化并发应用程序:第二部分(第 6 章 ~ 第 9 章)
活跃性、性能与测试:第三部分(第 10 章 ~ 第 12 章)
高级主题:第四部分(第 13 章 ~ 第 16 章)
第 1 章 简介
1. 线程的优势
发挥多处理器的强大能力
建模的简单性
异步事件的简化处理
响应更灵敏的用户界面
2. 线程带来的风险
安全性问题
活跃性问题
性能问题
第一部分 基础知识
第 2 章 线程安全性
1. 什么是线程安全
当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。
无状态对象一定是线程安全的。
2. 原子性
在并发编程中,由于不恰当的执行时序而出现不正确的结果是一种非常严重的情况,它有一个正式的名字:竞态条件(Race Condition)。
示例1:读取 - 修改 - 写入
@NotThreadSafe
public class UnsafeCountingFactorizer implement Servlet {
private long count = 0;
public lo ng getCount() { return count; }
public void service (ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
++count;
encodeIntoResponse(resp, factors);
}
}示例2:延迟初始化中的竞态条件
NotThreadSafe
public class LazyInitRace {
private ExpensiveObject instance = null;
public ExpensiveObject getInstance() {
if (instance == null) {
instance = new ExpensiveObject();
}
}
}原子操作是指,对于访问同一个状态的所有操作(包括该操作本身)来说,这个操作是一个以原子方式执行的操作。
在无状态的类中添加一个状态时,如果这个状态完全由线程安全的对象来管理,那么这个类仍然是线程安全的。然而,当状态变量的数量由一个变为多个时,就不那么简单了。
@ThreadSafe
public class CountingFactorizer implement Servlet {
private final AtomicLong count = new AtomicLong(0);
public lo ng getCount() { return count; }
public void service (ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
count.incrementAndGet();
encodeIntoResponse(resp, factors);
}
}在实际情况中,应尽可能的使用现有的线程安全对象(例如 AtomicLong)来管理类的状态。
评论