【问题标题】:Should I make all my java code threadsafe?我应该让我所有的java代码线程安全吗?
【发布时间】:2010-11-26 09:26:22
【问题描述】:

我正在阅读 Brian Goetze 的 Java Concurrency in Practice 中的一些并发模式,并且对何时是确保代码线程安全的正确时间感到困惑。

我通常编写在单线程中运行的代码,因此我不太担心线程安全和同步等问题。但是,始终存在相同的代码可能会在稍后的某个时间在多线程中重复使用的可能性-线程环境。

所以我的问题是,什么时候应该开始考虑线程安全?我应该在一开始就假设最坏的情况并始终从头开始编写线程安全代码,还是应该重新访问代码并在以后出现这种需要时修改线程安全?

是否有一些并发模式/反模式,即使在编写单线程应用程序时我也必须始终注意,以便我的代码以后在多线程环境中使用时不会中断?

【问题讨论】:

标签: java multithreading concurrency


【解决方案1】:

当您的代码将在多线程环境中使用时,您应该考虑线程安全。如果它只在单线程环境中运行,那么处理复杂性是没有意义的。

话虽如此,您可以做一些简单的事情,这些都是很好的做法,并且有助于多线程:

  1. 正如 Josh Bloch 所说,Favor Immutability。根据定义,不可变类几乎是线程安全的;
  2. 仅在需要而非方便时使用数据成员或静态变量。

【讨论】:

  • +1。此外,线程安全通常会带来性能损失。当它们与其他主要是线程安全的类共享包时,我通常会尝试记录线程不安全的类,以便规范的例外情况显而易见。
  • 如果一个函数被两个线程调用并且它们使用共享状态,那么争用就是一个问题。但是,如果他们所依赖的唯一状态是他们自己创建或传递的状态,则没有争用。
【解决方案2】:

使您的代码线程安全可以像添加注释一样简单,说明该类不是为多个线程并发使用而设计的。所以,从这个意义上说:是的,你所有的类都应该是线程安全的。

然而,在实践中,很多很多类型可能只被一个线程使用,通常只作为局部变量引用。即使整个程序是多线程的,情况也是如此。让每个对象都对多线程访问安全是错误的。虽然惩罚可能很小,但它是普遍存在的,并且可能会成为一个重大的、难以解决的性能问题。

【讨论】:

  • +1 提到使用 cmets 来说明设计意图
  • 我不会说“添加评论”与“使您的代码线程安全”相同。后者意味着类本身处理所有必要的同步。无论您的代码是否是线程安全的,其 Javadoc 中的注释都将节省其他程序员的时间和精力。 :)
【解决方案3】:

我建议您获取“Effective Java”,第 2 版的副本。约书亚布洛赫。那本书用一整章的篇幅来讨论并发性,包括对何时(何时不)进行同步的问题的深入探讨。请注意,例如,《Effective Java》中第 67 项的标题:“避免过度同步”,详细阐述了五页。

【讨论】:

  • 线程安全不一定需要同步。
【解决方案4】:

如前所述,当您认为您的代码将在多线程环境中使用时,您需要线程安全。

考虑Collections 类所采用的方法,您提供了一个线程不安全的类,它在不使用synchronize 的情况下完成所有工作,并且您还提供了另一个类来包装未同步的类并提供所有相同的公共方法,但使它们在底层对象上同步。

这让您的客户可以选择使用多线程或单线程版本的代码。它还可以通过将所有线程/锁定逻辑隔离在一个单独的类中来简化您的编码。

【讨论】:

    猜你喜欢
    • 2014-10-08
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-15
    • 1970-01-01
    相关资源
    最近更新 更多