线程安全
线程安全的对象具有在上面线程安全一节中描述的属性 由类的规格说明所规定的约束在对象被多个线程访问时仍然有效不管运行时环境如何排列线程都不需要任何额外的同步这种线程安全性保证是很严格的 许多类如 Hashtable 或者 Vector 都不能满足这种严格的定义
有条件的线程安全
我们在 月份的文件 并发集合类中讨论了有条件的线程安全有条件的线程安全类对于单独的操作可以是线程安全的但是某些操作序列可能需要外部同步条件线程安全的最常见的例子是遍历由 Hashtable 或者 Vector 或者返回的迭代器 由这些类返回的 failfast 迭代器假定在迭代器进行遍历的时候底层集合不会有变化为了保证其他线程不会在遍历的时候改变集合进行迭代的线程应该确保它是独占性地访问集合以实现遍历的完整性通常独占性的访问是由对锁的同步保证的 并且类的文档应该说明是哪个锁(通常是对象的内部监视器(intrinsic monitor))
如果对一个有条件线程安全类进行记录那么您应该不仅要记录它是有条件线程安全的而且还要记录必须防止哪些操作序列的并发访问用户可以合理地假设其他操作序列不需要任何额外的同步
线程兼容
线程兼容类不是线程安全的但是可以通过正确使用同步而在并发环境中安全地使用这可能意味着用一个 synchronized 块包围每一个方法调用或者创建一个包装器对象其中每一个方法都是同步的(就像 CollectionssynchronizedList() 一样)也可能意味着用 synchronized 块包围某些操作序列为了最大程度地利用线程兼容类如果所有调用都使用同一个块那么就不应该要求调用者对该块同步这样做会使线程兼容的对象作为变量实例包含在其他线程安全的对象中从而可以利用其所有者对象的同步
许多常见的类是线程兼容的如集合类 ArrayList 和 HashMap javatextSimpleDateFormat 或者 JDBC 类 Connection 和 ResultSet
线程对立
线程对立类是那些不管是否调用了外部同步都不能在并发使用时安全地呈现的类线程对立很少见当类修改静态数据而静态数据会影响在其他线程中执行的其他类的行为这时通常会出现线程对立线程对立类的一个例子是调用 SystemsetOut() 的类
其他线程安全记录考虑
线程安全类(以及线程安全性程度更低的的类) 可以允许或者不允许调用者锁定对象以进行独占性访问 Hashtable 类对所有的同步使用对象的内部监视器但是 ConcurrentHashMap 类不是这样事实上没有办法锁定一个 ConcurrentHashMap 对象以进行独占性访问除了记录线程安全程序还应该记录是否某些锁 如对象的内部锁 对类的行为有特殊的意义
通过将类记录为线程安全的(假设它确实 是线程安全的)您就提供了两种有价值的服务您告知类的维护者不要进行会影响其线程安全性的修改或者扩展您还告知类的用户使用它时可以不使用外部同步通过将类记录为线程兼容或者有条件线程安全的您就告知了用户这个类可以通过正确使用同步而安全地在多线程中使用通过将类记录为线程对立的您就告知用户即使使用了外部同步他们也不能在多线程中安全地使用这个类不管是哪种情况您都在潜在的严重问题出现 之前防止了它们而要查找和修复这些问题是很昂贵的
结束语
一个类的线程安全行为是其规格说明中的固有部分应该成为其文档的一部分因为(还)没有描述类的线程安全行为的声明式方式所以必须用文字描述虽然 Bloch 的描述类的线程安全程度的五层系统没有涵盖所有可能的情况但是它是一个很好的起点如果每一个类都将这种线程行为的程度加入到其 Javadoc 中那么可以肯定的是我们大家都会受益
[] []