gpt4 book ai didi

java - 如果您只有一个写线程,您是否需要特殊的并发性?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:57:09 25 4
gpt4 key购买 nike

假设:

  1. 只有一个特定的线程曾经设置过某个引用字段(不是 long 或 double,所以写入它是原子的)
  2. 可以有任意数量的线程读取同一个字段
  3. 稍微过时的读取是可以接受的(最多几秒钟)

在这种情况下,您是否需要 volatile 或 AtomicReference 或类似的东西?

This article状态:

Memory barriers are not required if you adhere strictly to the single writer principle.

这似乎表明,在我描述的情况下,您真的不需要做任何特别的事情。

所以,这是我运行的测试,结果很奇怪:

import org.junit.Test;

public class ThreadTest {
int onlyWrittenByMain = 0;
int onlyWrittenByThread = 0;

@Test
public void testThread() throws InterruptedException {
Thread newThread = new Thread(new Runnable() {
@Override
public void run() {
do {
onlyWrittenByThread++;
} while (onlyWrittenByMain < 10 || onlyWrittenByThread < 10);
System.out.println("thread done");
}
});
newThread.start();

do {
onlyWrittenByMain++;
// Thread.yield();
// System.out.println("test");
// new Random().nextInt();
} while (onlyWrittenByThread < 10);
System.out.println("main done");
}
}

有时运行它会输出“thread done”然后永远挂起。有时它确实完成了。所以线程看到主线程所做的更改,但显然主线程并不总是看到线程所做的更改?

如果我将系统放入,或 Thread.yield,或随机调用,或使 onlyWrittenByThread 可变,它每次都会完成(尝试了大约 10 次以上)。

这是否意味着我上面引用的博文不正确?即使在单写入器场景中,您也必须有内存屏障?

没有人完全回答这个问题,所以我想我猜想不需要内存屏障可能是正确的,但是如果没有创建 happens-before 关系的东西,java 编译器和热点可以进行优化(例如。吊装),这将使它不能做我们想做的事。

最佳答案

问题是在多核系统上缓存 - 如果没有类似 volatile 的东西强制 happens-before 关系(内存屏障的东西)你可以让你的编写器线程写入其核心和所有读者缓存中的变量副本线程在另一个核心上读取变量的另一个副本。另一个问题是原子性,另一个答案解决了这个问题。

关于java - 如果您只有一个写线程,您是否需要特殊的并发性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16990971/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com