【问题标题】:If more than one thread can access a field should it be marked as volatile?如果多个线程可以访问一个字段,是否应该将其标记为 volatile?
【发布时间】:2010-12-09 22:33:52
【问题描述】:

读取几个线程(common concurrency problemsvolatile keywordmemory model)我对 Java 中的并发问题感到困惑。

我有很多字段被多个线程访问。我应该遍历它们并将它们都标记为易失性吗?

在构建一个类时,我不知道是否有多个线程会访问它,所以让任何字段 not 易失肯定是不安全的,所以据我了解,您不会不要使用它。这是正确的吗?

对我来说,这是针对 1.5 版 JVM 及更高版本的,但不要局限于回答我的具体设置。

【问题讨论】:

    标签: java memory atomic volatile


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 对于这个特定的用例,请参阅 AtomicInteger,而不是自己使用 synchronized
    • 确实如此。我只是想展示盲目使用synchronized 的陷阱,而没有确切了解它的作用和不提供什么
    【解决方案2】:

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

    1. 他们会改变吗?如果没有,你不需要 volatile
    2. 如果是,那么一个字段的值是否与另一个字段相关?如果是,请转到第 4 点
    3. 有多少线程会改变它?如果只有 1,那么 volatile 就是你所需要的
    4. 如果数字 2 的答案是“否”或多个线程将写入它,那么仅 volatile 是不够,您可能需要同步访问李>

    添加:
    如果该字段引用了一个对象,那么它将有自己的字段,所有这些考虑也适用于这些字段。

    【讨论】:

      【解决方案3】:

      如果一个字段被多个线程访问,它应该是volatilefinal,或者只使用同步块访问。否则,分配的值可能对其他线程不可见。

      一个类必须专门为多个线程的并发访问而设计。简单地将字段标记为 volatile 或 final 不足以保证线程安全。存在一致性问题(多个字段更改的原子性)、线程间信号问题(例如使用waitnotify)等。

      因此,最安全的做法是假设一个对象只对单个线程可见,除非另有说明。使您的所有对象都成为线程安全的不是必需的,而且成本很高——就软件速度而言,但更重要的是,就开发费用而言。

      相反,软件的设计应使并发线程之间的交互尽可能少,最好完全不交互。需要清楚地识别它们交互的点,以便设计适当的并发控制。

      【讨论】:

        【解决方案4】:

        简短的回答是否定的。线程问题需要比这更多的思考和计划。请参阅this 了解有关 volatile 何时有助于线程以及何时没有的一些限制。值的修改必须正确同步,但非常典型的修改需要一次多个变量的状态。例如,假设您有变量,并且如果它符合条件,您想更改它。从数组读取和写入数组是不同的指令,需要一起同步。易挥发是不够的。

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

        【讨论】:

          猜你喜欢
          • 2019-04-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-25
          • 1970-01-01
          • 2013-04-11
          相关资源
          最近更新 更多