Effective Java(66~70)

本文探讨了线程安全的概念及实现方式,包括避免共享可变数据、减少同步操作、使用高级并发工具等内容,旨在帮助开发者更好地理解并实践多线程编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第66条 同步访问共享的可变数据

尽量避免在线程间共享可变数据,将可变数据限制在单线程中。让线程短时间修改一个对象,并与其他线程共享,这是可以接受的,只需要同步修改的动作即可。不需要同步,其他线程也可以读取该对象,只要它以后没有再改变。总的来说,如果想要多个线程共享可变数据,那么读写都需要进行同步。

第67条 避免过度同步

为了避免死锁和数据破坏。千万不要从同步区域内部调用外来方法。更为一般的讲,要尽量限制同步区域内部的工作量。当你在设计一个可变类的时候,要考虑一下他们是否应该自己完成同步操作。在现在这个多核的时代,这比永远不要过度同步来得更重要。只有当你有足够的理由一定要在内部同步类的时候,才应该这么做,同时还应该将这个决定清楚地写到文档中。

第68条 executor和task优于线程

如果编写的是小程序,或者轻载的服务器,使用Executor.newCachedThreadPool通常是个不错的选择。 
在大负载的服务器中,最好使用Executor.newFixedThreadPool,它为你提供了一个包含固定线程数目的线程池,或者为了最大限度的控制它,就直接使用ThreadPoolExecutor类。

第69条 并发工具优先于wait和notify

优先使用java.util.concurrent包中提供的更高级的语言来代替wait,notify

第70条 线程安全性的文档化

首先说一个错误的观点是“只要是加了synchronized关键字的方法或者代码块就一定是线程安全的,而没有加这个关键字的代码就不是线程安全的”。这种观点认为“线程安全要么全有要么全无”,事实上这是错误的。因为线程安全包含了几种级别:

  1. 不可变的(Immutable):类的实例不可变(不可变类),一定线程安全,如String、Long、BigInteger等。
  2. 无条件的线程安全(Unconditionally ThreadSafe):该类的实例是可变的,但是这个类有足够的的内部同步。所以,它的实例可以被并发使用,无需任何外部同步,如Random和ConcurrentHashMap。
  3. 有条件的线程安全(Conditionally ThreadSafe):某些方法需要为了安全的并发而在外部进行同步,其余方法与无条件的线程安全一致。如Collection.synchronized返回的集合,对它们进行迭代时就需要外部同步。如下代码,当对synchronizeColletcion返回的 collection进行迭代时,用户必须手工在返回的 collection 上进行同步,不遵从此建议将导致无法确定的行为。
  4. 非线程安全(UnThreadSafe):该类是实例可变的,如需安全地并发使用,必须外部手动同步。如HashMap和HashSet。
  5. 线程对立的(thread-hostile):即便所有的方法都被外部同步保卫,这个类仍不能安全的被多个线程并发使用。这种情况的类很少,不常用。

每个类都应该利用字斟句酌的说明或者线程安全注解,清楚地在文档中说明它的线程安全属性,synchronized修饰符与这个文档毫无关系。有条件的线程安全类必须在文档中指明“哪个方法调用序列需要外部同步,以及在执行这些序列的时候要获得哪把锁”。如果你编写的是无条件的线程安全类,就应该考虑使用私有锁对象来代替同步的方法。这样可以放置客户端程序和子类的不同步干扰,让你能够在后续的版本中灵活地对并发控制采用更加复杂的方法。

  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值