准则一 对共享可变数据的同步访问
当多个线程共享可变数据时,每个读取或写入数据的线程都必须执行同步。 在缺乏同步的情况下,不能保证一个线程的更改对另一个线程可见。同步共享可变数据失败的代价是活性失败和安全失败。
准则二 避免过度同步
为避免活性失败和安全故障,永远不要在同步方法或块中将控制权交给客户端。
作为规则,你应该在同步区域内做尽可能少的工作。 获取锁,检查共享数据,根据需要进行转换,然后删除锁。如果你必须执行一些耗时的活动,请设法将其移出同步区域。
为了避免死锁和数据损坏,永远不要从同步区域内调用外来方法。更一般地说,将你在同步区域内所做的工作量保持在最小(也是降低锁的粒度)。
注解什么是外来方法:通常指的是在一个线程或同步区域中调用另一个线程或不同同步区域的方法。
准则三 Executor、task、流优于直接使用线程
这个准则告诉我们尽量使用线程池去执行任务。
准则四 并发实用工具优于 wait 和 notify
考虑到正确使用 wait 和 notify 的困难,你应该使用更高级别的并发实用工具。
准则五 文档应包含线程安全属性
比如下面这个代码就是完全延迟加载的,并且线程安全。
private volatile FieldType field;
private FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
if (field == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
准则五 不要依赖线程调度器
不要依赖 Thread.yield 或线程优先级。这些工具只是对调度器的提示。线程优先级可以少量地用于提高已经工作的程序的服务质量,但绝不应该用于「修复」几乎不能工作的程序。