java - 类变量以外的对象的易变性

标签 java multithreading concurrency volatile

我曾经相信任何在两个线程之间共享的变量都可以在线程本地缓存,并且应该声明为 volatile。但这种信念最近受到了一位队友的挑战。我们正在尝试确定在以下情况下是否需要 volatile。

class Class1
{
   void Method1()
   {
      Worker worker = new Worker();
      worker.start();
      ...
      System.out.println(worker.value); // want to poll value at this instant
      ...
   }

   class Worker extends Thread
   {
      int value = 0; // Should this be declared as a volatile?
      public void run()
      {
         ...
         value = 1; // this is the only piece of code that updates value
         ...
       }
   }
}

现在我的观点是,Worker(子)线程可能已经在线程中缓存了 Worker 对象的变量“值”,并更新了它的副本,同时将值设置为 1。在这种情况下,主线程可能看不到更新后的值。

但我的队友认为,由于对“值”的访问是通过一个对象(worker)发生的,因此对于两个线程来说,看到不同的值,只有当两个线程都维护“worker”的单独副本时才有可能"对象本身(这进一步意味着线程的创建涉及创建所有共享对象的深拷贝)。

现在我知道这不可能是真的,因为如果每个线程都维护所有共享对象的完全不同的副本,那将是非常低效的。因此,我对此深表怀疑。在主线程中执行“worker.value”是否引用与在子线程中执行“this.value”不同的内存位置?子(Worker)线程会缓存“值”吗?

问候。

最佳答案

Now my contention is that, it is possible that the Worker (child) thread could have cached the variable "value" of the Worker object thread-locally and updated just it's copy while setting the value to 1. In such a case, main thread may not see the updated value.

你是对的。即使你们都在处理同一个 Worker 实例,也不能保证 Worker 字段的缓存内存版本在各种不同的线程内存之间同步缓存。

value 字段必须标记为 volatile 以保证其他线程将看到 value = 1; 更新到 字段。

But my teammate believes that since the access to "value" is happening through an object (worker), therefore for both the threads to see different values, it could only be possible if both the threads were maintaining separate copies of "worker" object itself...

不,这是不正确的。关于线程内存的棘手部分围绕着处理器内存缓存。没有 volatile 强加的内存屏障,进程可以完全自由地缓存内存。因此,即使两个线程都在使用 Worker 的同一个实例,它们也可能具有与 Worker 关联的内存的本地缓存副本 .

线程架构获得了很大的速度,因为它们使用单​​独的高速处理器本地内存,而不是总是引用中央存储。

关于java - 类变量以外的对象的易变性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11054259/

相关文章:

java - 在改造中处理超过 1 个响应

java - 通用编程有必要吗?

java - OnSensorChanged线程

java - 哪个方法用于运行线程?

haskell - 为什么 Haskell 中没有隐式并行性?

java - 如何通过命令行更新 Eclipse 的 jre 位置?

java - 如何使用 Jackson 正确序列化/反序列化 java.time.DayOfWeek?

python - 从子线程中断主线程的 raw_input()

language-agnostic - 您如何处理/响应 GUI 层上的用户输入并发性?

java - JButton 不工作[捕获网络流量]