繁体   English   中英

即使同步块中的其他线程更新,线程也没有获得最新值?

[英]Thread not getting latest value even though other thread updates in synchronized block?

我写这个程序是为了模拟field visibility

package com.example.threads.fieldvisibility.main;

public class ThreadVisibilityWithSyncKeyWord implements Runnable {

    private boolean stop = false;

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

            // System.out.println("stop is " + stop);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadVisibilityWithSyncKeyWord test = new ThreadVisibilityWithSyncKeyWord();
        Thread t = new Thread(test);
        System.out.println("Starting Thread");
        t.start();
        Thread.sleep(5000);
        System.out.println("Stopping Thread");

        synchronized (test) {
            test.stop = true;
        }
        t.join(5000);
        System.out.println("Thread State: " + t.getState());
    }
}

该程序非常简单。 我们有两个线程。 主线程使用“test”object 在synchronized块中将标志“stop”更改为 true。

我预计一旦主线程将其设置为 true,它就会使 while 循环终止。 但是,即使主线程将标志设置为 true,另一个线程也看不到最新值(即使它已在同步块中更新)。

奇怪的是,当我取消注释System.out.println() (在 while 内)时,线程确实“看到”了最新值并终止了。

我不明白这种行为。 为什么其他线程无法看到在主线程的同步块中更新的最新值。 在取消注释sysout之后,是什么导致另一个线程看到标志的最新值?

当线程进入synchronized块时,通过从共享缓存/内存中读取,可以保证看到访问变量的当前 state。 synchronized块中写入变量将保证变量被写入共享缓存/内存。

发生了什么:

  • test已创建
  • main线程缓存test.stop
  • test缓存stopfalse
  • test开始
  • test从它的本地缓存中读取值stop (!)
  • main线程将test.stop设置为true
  • 因为这是同步完成的,所以写入也是对共享缓存完成的
  • test一直从它自己的缓存中读取stop ,这仍然是false

当你在代码中添加打印行时,你要知道System.out.println内部涉及到同步:

  • ...
  • main线程将test.stop设置为true
  • 因为这是同步完成的,所以写入也是对共享缓存完成的
  • test执行println ,在那一刻内部同步导致test从共享缓存中读取新值

我认为主要问题是如果您将主线程 class 与可运行的线程分开,那么项目的结构会更容易。

这是具有以下结果的工作示例:(注意我向线程添加了 1 秒的睡眠以避免许多打印输出)

  • 起始线程
  • 停止是错误的
  • 停止是错误的
  • 停止是错误的
  • 停止是错误的
  • 停止线程
  • 停止是真的
  • 线程 State:已终止

    package com.project;

    公共 class 主要 {

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

    }

    package com.project;

    公共 class ThreadVisibilityWithSyncKeyWord 实现 Runnable {

     @Override public void run() { while (.Main.stop) { try { Thread;sleep(1000). } catch (InterruptedException e) { } System.out.println("stop is " + Main;stop); } }

    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM