这个变量需要声明为 volatile 吗?

发布于 2024-09-03 06:21:12 字数 863 浏览 1 评论 0原文

在此代码中,MyThread 类中的 out 变量是否需要声明为 volatile,或者 ThreadTest 类中的 stdout 变量的“波动性”会保留吗?

import java.io.PrintStream;

class MyThread implements Runnable
{
    int id;
    PrintStream out; // should this be declared volatile?

    MyThread(int id, PrintStream out) {
        this.id = id;
        this.out = out;
    }

    public void run() {
        try {
            Thread.currentThread().sleep((int)(1000 * Math.random()));
            out.println("Thread " + id);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class ThreadTest
{
    static volatile PrintStream stdout = System.out;

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new MyThread(i, stdout)).start();
        }
    }
}

Does the out variable in the MyThread class need to be declared volatile in this code or will the "volatility" of the stdout variable in the ThreadTest class carry over?

import java.io.PrintStream;

class MyThread implements Runnable
{
    int id;
    PrintStream out; // should this be declared volatile?

    MyThread(int id, PrintStream out) {
        this.id = id;
        this.out = out;
    }

    public void run() {
        try {
            Thread.currentThread().sleep((int)(1000 * Math.random()));
            out.println("Thread " + id);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class ThreadTest
{
    static volatile PrintStream stdout = System.out;

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new MyThread(i, stdout)).start();
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

聚集的泪 2024-09-10 06:21:12

易失性 限定符不会执行,并且它在上面的代码中没有任何作用。易失性在变量的读写上建立了内存屏障,一旦在构造函数中初始化,就永远不会被修改。出于同样的原因,ThreadTest 中的 volatile 限定符也没有任何作用。

需要明确的是,易失性适用于变量,而不是引用的对象。

The volatile qualifier won't carry through, and it serves no purpose in the above code. Volatile establishes a memory barrier on reads and writes to the variable, which is never modified once initialised in the constructor. For the same reason, the volatile qualifier in ThreadTest serves no purpose either.

Just to be clear, volatile applies to the variable, not to the referenced object.

思念满溢 2024-09-10 06:21:12

在此代码中,MyThread 类中的 out 变量是否需要声明为 volatile,或者 ThreadTest 类中 stdout 变量的“波动性”是否会延续?

波动性不会“延续”,因为您实际上传递了变量的值。

根据我对JLS内存模型的阅读 规范,如果您要在创建对象的线程和使用该对象的线程之间没有任何干预同步的情况下读取out,则需要易失性它。

在编写的代码中,面临风险的变量是out。这是一个非私有变量,可以被任何东西访问/更新
可以访问该类。您的示例中没有代码可以执行此操作,但您可以编写另一个类...或更改 ThreadTest。

但在这种情况下,更好的解决方案是:

  • 声明outfinalfinal 字段的语义 表示不需要同步。

  • out声明为私有。现在,线程构造和 start() 调用之间的“happens-before”确保了对 out 唯一可能的访问将看到正确的值。

Does the out variable in the MyThread class need to be declared volatile in this code or will the "volatility" of the stdout variable in the ThreadTest class carry over?

The volatility does not "carry over" because you actually passing the value of the variable.

According to my reading of the JLS memory model spec, a volatile is required if you were to read out without some intervening synchronization between the thread that created the object and the thread that uses it.

In the code as written, the variable at risk is out. Which is a non-private variable, and could be accesses / updated by anything that
has access to the class. There is no code in your example that does that, but you could write another class ... or change ThreadTest.

But in this case better solutions would be:

  • Declare out as final. The semantics of final fields mean that no synchronization is required.

  • Declare out as private. Now the "happens-before" between the thread's construction and the start() call ensures that the only possible access to out will see the right value.

随风而去 2024-09-10 06:21:12

肯定不会延续下去。不过,我不确定你想做什么。 volatile 限定 ThreadTest 中的字段,而不是值。

It definitely won't carry over. I'm not sure what you're trying to do, though. volatile qualifies the field in ThreadTest, not the value.

甜中书 2024-09-10 06:21:12

没有必要。

因为之间有happens-before
在调用 Thread.start 之前和调用 Thread.start 之后创建的对象

is not necessary.

Because there is happens-before between
objects that are created before the call Thread.start and after the call Thread.start

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文