在 Java 中模拟 Field-visibility 问题 [英] Simulating Field-visibility problem in Java

查看:52
本文介绍了在 Java 中模拟 Field-visibility 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读有关 Java 内存模型的教程之一,并遇到了在多线程编程中发生的字段可见性 的概念.我尝试使用以下代码模拟相同的内容,但是,我在每个线程中看到,最新值正在反映(在 ReaderThread 中).

I was going through one of the tutorials on memory model of Java and came across this concept of field visibility which happens in multi-threaded programming. I tried to simulate the same using the below code, however , I see in each thread, the latest value is being reflected (in ReaderThread).

以下是完整的程序.

在使用 while(somevariable) 的一些建议之后,我合并了,但仍然得到相同的行为.我在阅读 x

After some suggestion to use while(somevariable), I incorporated, but still getting the same behaviour. I removed sysout on reading the x

FieldVisibility.java

package com.example.threads.fieldvisibility;

public class FieldVisibility {

    private int x;

    private boolean condition;

    public FieldVisibility() {
        condition = true;
    }

    public void reader() {

        System.out.println("x in reader() is " + x);
    }

    public void writer() {
        x++;

    }

    public boolean getCondition() {
        return condition;
    }

    public void setCondition(boolean condition) {
        this.condition = condition;
    }
}

ReaderThread.java

package com.example.threads.fieldvisibility;

public class ReaderThread extends Thread {

    private FieldVisibility fv;

    public ReaderThread(FieldVisibility fv) {
        this.fv = fv;

    }

    @Override
    public void run() {

        while (fv.getCondition()) {

            System.out.println("It mean condition is true, which was set initially");

        }
        for (;;) {

        }
    }
}

WriterThread.java

package com.example.threads.fieldvisibility;

public class WriterThread extends Thread {

    private FieldVisibility fv;

    public WriterThread(FieldVisibility fv) {
        this.fv = fv;

    }

    @Override
    public void run() {

        fv.setCondition(false);
        for (;;) {

            fv.writer();
        }

    }
}

MainApp.java

package com.example.threads.fieldvisibility.main;

import com.example.threads.fieldvisibility.FieldVisibility;
import com.example.threads.fieldvisibility.ReaderThread;
import com.example.threads.fieldvisibility.WriterThread;

public class MainApp {

    public static void main(String[] args) throws InterruptedException {

        FieldVisibility fv = new FieldVisibility();

        ReaderThread rt = new ReaderThread(fv);
        WriterThread wt = new WriterThread(fv);

        wt.start();

        rt.start();

        Thread.sleep(999999999L);
    }
}

编辑

我在FieldVisibility中添加了一个新变量condition,默认值为true.接下来,我在 WriterThread 中将它的值设置为 false,但是,相同的值(false)仍然传播到 ReaderThread,所以我仍然是无法模拟它.

Edit

I added a new variable condition in FieldVisibility, whose default values is true. Next, I set its value to false in WriterThread, however, the same value (false) is still propagated to ReaderThread, so I still am not able to simulate it.

原创我预计在某个时候 ReaderThread 将无法看到"变量 x 的最新值,但是我每次运行它时都看到,它给出了相同的结果.我什至在调试模式下运行,在连续运行 WriterThread 的同时暂停 ReaderThread.但这也没有阻止 ReaderThread 获得最新值.我希望我需要将变量 x 声明为 volatile 以便 ReaderThread 读取 x 的最新值.

Original I expected that at some time ReaderThread won't be able to "see" the latest value of variable x, but I saw every time I run it, it gave same results. I even run in debug mode, suspended ReaderThread while running WriterThread continuously. But that also didn't prevent ReaderThread to have latest values. I expected that I need to declare variable x as volatile in order for ReaderThread to read latest values of x.

我如何模拟字段可见性的概念,或者我需要为此做哪些改变?

How can I simulate the field visibility concept, or what changes I need to do for this?

推荐答案

您的示例不起作用,因为 System.out.println() 使用共享资源 (System.out),所以它会与同一资源的其他用途同步.

Your example doesn't work because System.out.println() uses a shared resource (System.out), so it will synchronize with other uses of the same resource.

因此,您永远不会*看到一个线程使用另一个线程的旧值的结果.(*理论上读者可以在x++和对应的System.out.println()

Therefore you will never* see a result where one thread uses the old value of the other. (*in theory it is possible for the reader to read x between x++ and the corresponding System.out.println()

以下是使用旧值的示例:

Here is an example where a old value is used:

public class ThreadVisibility implements Runnable {

    private boolean stop = false;

    @Override
    public void run() {
        while (!stop);
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadVisibility test = new ThreadVisibility();
        Thread t = new Thread(test);
        t.setDaemon(true);
        System.out.println("Starting Thread");
        t.start();
        Thread.sleep(1000);
        System.out.println("Stopping Thread");
        test.stop = true;
        t.join(1000);
        System.out.println("Thread State: " + t.getState());
    }
}

如果你运行这段代码,最后会显示线程仍在运行.如果没有 t.setDaemon(true),VM 将等待线程完成,这永远不会发生.

If you run this code, it will display that the thread is still running at the end. Without the t.setDaemon(true), the VM would wait for the Thread to finish, which would never happen.

如果您注释掉 Thread.sleep,那么新线程可能会终止(至少在我的测试中是这样),但不能保证会终止.
解决此问题的正确方法是声明 stop volatile.
或者添加一个内存屏障.

If you comment out the Thread.sleep, then the new Thread may terminate (at least it did in my tests), but it is not guaranteed to.
The right fix for this problem is to declare stop volatile.
Or add a memory barrier.

这篇关于在 Java 中模拟 Field-visibility 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆