【问题标题】:Java Synchronized question, communicate between the threadsJava同步问题,线程间通信
【发布时间】:2020-02-01 10:53:46
【问题描述】:

请看下面的代码。我知道为什么我不使用“同步”部分,循环永远不会中断,但我不知道为什么我使用“同步”部分,循环会中断。好像不符合 Happens-Before 原则。请帮帮我,非常感谢。

public class Test implements Runnable {

    private String s = "continue";

    @Override
    public void run() {

        while (!"break".equals(this.s)) {
            //synchronized (this){
            //
            //}
        }

        System.out.println("loop has been breaked!");
    }

    public static void main(String[] args) throws InterruptedException {
        Test test = new Test();

        Thread t1 = new Thread(test);
        t1.start();

        TimeUnit.SECONDS.sleep(1);
        test.s = "break";
    }

}

【问题讨论】:

    标签: java multithreading concurrency locking


    【解决方案1】:

    这不是发生之前的情况,而是可见性问题。使s volatile 也可以工作,使值更改对线程可见,而不是使用缓存值。

    从 Java 内存模型的 POV 来看,使用同步的方式是不正确的。分配test.s = "break"; 时,您还需要在test 上同步。但是,由于底层 x86 架构,您的同步代码可以工作,即使使用 NOOP 同步块也会影响可见性。

    【讨论】:

    • 谢谢,我知道添加 volatile 会起作用,让我困惑的是会添加 syn 部分使 s 值更改可见。不要添加 s 值更改不可见的 syn 部分。
    • @RichardH。这真的是一个副作用。在不同的架构上,它可能会以不同的方式工作。
    • 能否请您说的更具体一些,
    • 如果我将同步部分添加到while循环之外,它也不会中断。
    • @RichardH。这是有道理的,从那时起线程一直在同步块内。但这是涉及字节码、x86 操作码和各种内容的细节,这些内容太长,无法在此解释。更不用说我不是给出技术上正确答案的最佳人选。一个简化的答案是“这些是副作用,您的程序在技术上是错误的,但由于 x86 架构而恰好可以工作”。
    猜你喜欢
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2011-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多