java - 线程之间是否共享静态变量?

标签 java multithreading concurrency static memory-visibility

我在高级 Java 线程类(class)中的老师说了一些我不确定的话。

他表示以下代码不一定会更新 ready 变量。据他介绍,两个线程不一定共享静态变量,特别是在每个线程(主线程与 ReaderThread)都在自己的处理器上运行并且因此不共享相同的情况下寄存器/缓存/等,一个 CPU 不会更新另一个。

本质上,他说 ready 可能在主线程中更新,但不在 ReaderThread 中,因此 ReaderThread 将无限循环。

他还声称程序可以打印 042。我了解如何打印 42,但不了解 0。他提到当 number 变量设置为默认值时会出现这种情况。

我想也许不能保证在线程之间更新静态变量,但这让我觉得 Java 很奇怪。使 ready volatile 能解决这个问题吗?

他展示了这段代码:

public class NoVisibility {  
    private static boolean ready;  
    private static int number;  
    private static class ReaderThread extends Thread {   
        public void run() {  
            while (!ready)   Thread.yield();  
            System.out.println(number);  
        }  
    }  
    public static void main(String[] args) {  
        new ReaderThread().start();  
        number = 42;  
        ready = true;  
    }  
}

最佳答案

就可见性而言,静态变量并没有什么特别之处。如果它们可以访问,任何线程都可以访问它们,因此您更有可能看到并发问题,因为它们更容易暴露。

JVM 的内存模型存在可见性问题。 Here's an article talking about the memory model and how writes become visible to threads .你不能指望一个线程让其他线程及时看到更改(实际上 JVM 没有义务在任何时间范围内让这些更改对你可见),除非你建立一个 happens-before relationship .

这是来自该链接的引用(由 Jed Wesley-Smith 在评论中提供):

Chapter 17 of the Java Language Specification defines the happens-before relation on memory operations such as reads and writes of shared variables. The results of a write by one thread are guaranteed to be visible to a read by another thread only if the write operation happens-before the read operation. The synchronized and volatile constructs, as well as the Thread.start() and Thread.join() methods, can form happens-before relationships. In particular:

  • Each action in a thread happens-before every action in that thread that comes later in the program's order.

  • An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.

  • A write to a volatile field happens-before every subsequent read of that same field. Writes and reads of volatile fields have similar memory consistency effects as entering and exiting monitors, but do not entail mutual exclusion locking.

  • A call to start on a thread happens-before any action in the started thread.

  • All actions in a thread happen-before any other thread successfully returns from a join on that thread.

关于java - 线程之间是否共享静态变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4934913/

相关文章:

Java 并发收集少写多读

java - 具有 stomp 安全性的 Spring websocket - 每个用户都可以订阅任何其他用户队列?

linux - 使用 pthread 的工作队列

Python随时捕获用户输入

java - 避免 boolean 翻转的同步块(synchronized block)

java - sbt汇编上的Java OutOfMemoryError

java - jni- 释放对象数组

Python 多线程/处理模块,用于具有需要排序的依赖项的任务

go - Mutex 似乎没有正确锁定

java - 是否可以安排 CompletableFuture?