阅读几个主题(常见的并发问题 volatile关键字内存模型)我对并发问题感到困惑Java的。

我有很多字段可以被多个线程访问。我是否应该通过它们并将它们标记为易变?

在构建一个类时,我不知道多个线程是否会访问它,所以肯定让任何字段变得不稳定是不安全的,所以根据我的理解,你很少会遇到这种情况。不要用它。这是对的吗?

对我而言,这是针对1.5版JVM及更高版本的,但不仅限于回答我的具体设置。

有帮助吗?

解决方案

如果一个字段被多个线程访问,它应该是 volatile final ,或者只能使用synchronized块访问。否则,指定的值可能对其他线程不可见。

必须专门为多个线程的并发访问设计类。简单地标记易失性或最终的字段对于线程安全是不够的。存在一致性问题(多个字段的更改的原子性),关于线程间信令的关注(例如,使用 wait notify )等。

因此,最安全的做法是假设一个对象应该只对一个线程可见,除非另有说明。使所有对象都是线程安全的并不是必需的,并且在软件速度方面成本很高,但更重要的是,在开发费用方面。

相反,应该设计软件,以便并发线程尽可能少地相互交互,最好不要。需要明确识别它们进行交互的点,以便设计适当的并发控制。

其他提示

嗯,你已经阅读了其他问题,我认为你已经阅读了答案,所以我只想强调一些要点:

  1. 他们会改变吗?如果没有,你不需要易变的
  2. 如果是,那么是与另一个相关的字段的值吗?如果是,请转到第4点
  3. 有多少线程会改变它?如果只有1,那么就是你需要的所有东西
  4. 如果对数字2的答案是“否”,则或者多个线程要写入它,然后单独的volatile 不够,你可能需要同步访问
  5. 添加了:结果, 如果该字段引用一个Object,那么它将具有自己的字段,所有这些考虑也适用于这些字段。

如果你不得不问,请使用锁。在某些情况下, volatile 会很有用,但要正确起来非常非常困难。例如:

class Foo {
  private volatile int counter = 0;
  int Increment() {
    counter++;
    return counter;
  }
}

如果两个线程同时运行 Increment(),则结果可能是 counter = 1 。这是因为计算机将首先检索 counter ,添加一个,然后将其保存。 Volatile只是强制保存和加载以相对于其他语句的特定顺序发生。

请注意, synchronized 通常不需要 volatile - 如果对给定字段的所有访问都受同一监视器的保护, volatile 将永远不需要。

使用 volatile 来制作无锁算法非常非常困难;坚持 synchronized ,除非你有确凿的证据表明它已经太慢了,并且已经对你计划实施的算法做了详细的分析。

简短的回答是否定的。线程问题需要更多的思考和计划。请参阅,了解有关volatile何时有助于解决问题的一些限制线程,什么时候没有。必须正确地同步值的修改,但通常修改一次需要多个变量的状态。比如说你有变量,如果它符合标准你想要改变它。从数组读取和写入数组是不同的指令,需要同步。挥发性不够。

还要考虑变量引用可变对象(比如数组或集合)的情况,然后与该对象进行交互将不会是线程安全的,因为引用是易失性的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top