接近线程安全程序

时间:2010-10-11 01:14:58

标签: java concurrency thread-safety

所有

编写线程安全程序的方法应该是什么。鉴于问题陈述,我的观点是:

1>开始编写单线程环境的代码 2>为需要原子性的字段加下划线,并用可能的并发类替换 3>在临界区下划线并将它们包含在同步中 4>执行死锁测试

有没有人对我的方法的其他方法或改进有任何建议。到目前为止,我可以看到自己将大部分代码都包含在synchronized块中,我确信这不正确。

用Java编程

5 个答案:

答案 0 :(得分:3)

编写正确的多线程代码很难,并且没有一个神奇的公式或一组步骤可以帮助您。但是,您可以遵循一些指导原则。

就个人而言,我不会从编写单线程环境的代码开始,然后将其转换为多线程。良好的多线程代码从一开始就考虑到了多线程。字段的原子性只是并发代码的一个元素。

您应该决定代码的哪些区域需要多线程(在多线程应用程序中,通常不是所有内容都需要线程安全)。然后,您需要设计这些部分将如何线程安全。使代码线程安全的一个区域的方法可以与使其他区域不同的方法不同。例如,了解是否存在大量读取与写入是很重要的,并且可能会影响用于保护数据的锁类型。

不变性也是线程安全代码的关键要素。当元素是不可变的(即无法更改)时,您无需担心多个线程修改它们,因为它们无法更改。这可以大大简化线程安全问题,并使您可以专注于拥有多个数据读取器和编写器的位置。

了解Java中的并发性(以及Java内存模型的详细信息)非常重要。如果您还不熟悉这些概念,我建议您阅读Java Concurrency In Practice http://www.javaconcurrencyinpractice.com/

答案 1 :(得分:1)

您应尽可能使用最终不可变字段,将要更改的任何其他数据添加到内部:

  synchronized (this) {
     // update
  }

请记住,有时候会发生制动,如果发生这种情况,你不想通过采取一切可能的方法来延长程序执行时间,而不是“快速失败”。

答案 2 :(得分:1)

正如您所询问的“线程安全”而非并发性能,那么您的方法基本上是合理的。但是,使用同步的线程安全程序可能在多CPU环境中不会扩展太多,在您的结构/程序上存在任何级别的争用。

我个人喜欢尝试识别最高级别的状态更改,并尝试思考如何使它们成为原子状态,并让状态更改从一个不可变状态转移到另一个状态 - 如果您愿意,可以写入copy-on-write。然后,实际的写入可以是对原子变量的比较和设置操作,也可以是同步更新或任何策略工作/执行最佳(只要它安全地发布新状态)。

如果您的新状态完全不同(例如需要更新几个字段),这可能有点难以构建,但我已经看到它非常成功地解决了同步访问的并发性能问题。

答案 3 :(得分:1)

购买并阅读Brian Goetz的“Java Concurrency in Practice”。

答案 4 :(得分:0)

任何可能同时由多个线程访问的变量(内存)都需要通过同步机制进行保护。