java - 并发编程,线程之间共享值

标签 java multithreading concurrency busy-waiting

我是并发编程的初学者,我想确切地了解为什么当我在 get() 中注释 sleep(1) 时该程序没有结束> 我的第一个想法是 sleep(1) 将手交还给主线程,也许与忙等待有关?

public class Rdv<V> {
  private V value;

  public void set(V value) {
    Objects.requireNonNull(value);
    this.value = value;
  }

  public V get() throws InterruptedException {
    while(value == null) {
        Thread.sleep(1);  // then comment this line !
    }
    return value;
  }

  public static void main(String[] args) throws InterruptedException {
    Rdv<String> rendezVous = new Rdv<>();
    new Thread(() -> {
      try {
        Thread.sleep(5000);
      } catch (InterruptedException e) {
        throw new AssertionError(e);
      }
      rendezVous.set("hello");
    }).start();

    System.out.println(rendezVous.get());
  }
}

最佳答案

首先,这个程序被严重破坏了。即使 sleep 也不能保证它会终止。可能会,但也可能不会。

问题在于值字段不是 volatile 的,并且在获取/设置值时不使用同步锁或其他锁。这意味着无法保证一个线程会看到另一个线程所做的更改!正在等待的线程可能永远看不到应该停止程序的写入值。 sleep 到位后,一切正常,因为 Java 正在解释模式下运行。如果没有 sleep ,及时编译器就有时间启动并优化代码。它发现 while 循环可以重写为一个更高效的版本,它可以完成同样的事情:永远循环。这就是它的作用。

最简单的解决方法是将值字段声明为 volatile 的。然后 Java 知道它可能会发生变化并避免优化读取。

简短的版本,除非您很了解 Java 内存模型,否则始终同步对线程之间共享的数据的访问。安全总比后悔好!

关于java - 并发编程,线程之间共享值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47381284/

相关文章:

java - 等到使用 Latch 执行 Platform.runLater

java - 如何取消 FutureResult 执行

java - 在java中只运行线程一分钟

java - 文件的多线程读写,无法停止操作,写入错误文件

java - 使用notify将线程从其状态唤醒

java - matcher.group() 的内存分配

java - 未出现保存文件对话框

multithreading - 线程和同步

java - 永远的卡夫卡消费者民意调查

c - C 中的 WinAPI 文本输出