第66条 同步访问共享的可变数据
Java语言规范保证读或者写一个变量是原子的 除非这个变量的类型为long或者double 为了提高性能 在读或写原子数据的时候 应该避免使用同步 这个建议是非常危险而错误的 为了在线程之间进行可靠的通信 也为了互斥访问 同步是必要的
如果读和写操作没有都被同步 同步就不会起作用
将可变数据限制在单个线程中
当多个线程共享可变数据的时候 每个读或者写数据的线程都必须执行同步
第67条 避免过度同步
为了避免活性失败和安全性失败 在一个被同步的方法或者代码块中 永远不要放弃对客户端的控制
通常 应该在同步区域内做尽可能少的工作
第68条 executor和task优先于线程
第69条 并发工具优先于wait和notify
正确地使用wait和notify比较困难 就应该用更高级的并发工具来代替
并发集合中不可能排除并发活动 将它锁定没有什么作用 只会使程序的速度变慢
除非不得已 否则应该优先使用ConcurrentHashMap 而不是使用Collections.synchronizedMap或者Hashtable
对于间歇式的定时 始终应该优先使用System.nanoTime 而不是使用System.currentTimeMills System.nanoTime更加准确也更加精确 它不受系统的实时时钟的调整所影响
始终应该使用wait循环模式来调用wait方法 永远不要在循环之外调用wait方法
没有理由在新代码中使用wait和notify 即使有 也是极少的
第70条 线程安全性的文档化
在一个方法声明中出现synchronized修饰符 这是个实现细节 并不是导出的API的一部分
一个类为了可被多个线程安全地使用 必须在文档中清楚地说明它所支持的线程安全性级别
线程安全性的几种级别:
不可变的
无条件的线程安全
有条件的线程安全
非线程安全
线程对立的
第71条 慎用延迟初始化
在大多数情况下 正常的初始化要优先于延迟初始化
如果利用延迟优化来破坏初始化的循环 就要使用同步访问方法
如果出于性能的考虑而需要对静态域使用延迟初始化 就使用lazy initialization holder class模式
如果出于性能的考虑而需要对实例域使用延迟初始化 就使用双重检查模式
对于可以接受重复初始化的实例域 也可以考虑使用单重检查模式
第72条 不要依赖于线程调度器
任何依赖于线程调度器来达到正确性或者性能要求的程序 很有可能都是不可移植的
如果线程没有在做有意义的工作 就不应该运行
线程优先级是Java平台上最不可移植的特征了
Thread.yield的唯一用途是在测试期间人为地增加程序的并发性
第73条 避免使用线程组
因为线程组已经过时了 所以实际上根本没有必要修正