假设:
在这种情况下,您需要volatile或AtomicReference或类似的东西吗?
本文指出:
如果严格遵守单一编写原则,则不需要内存屏障.
这似乎表明,在我描述的情况下,你真的不需要做任何特别的事情.
所以,这是一个测试我跑了好奇的结果:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
有时运行它会输出"thread done"然后永远挂起.有时它确实完成了.所以线程看到主线程所做的更改,但显然main并不总是看到线程所做的更改?
如果我把系统放入,或者Thread.yield,或者随机调用,或者只使用DynamicWyThread,它每次都会完成(尝试大约10次以上).
这是否意味着我上面提到的博客文章不正确?即使在单个编写器场景中,您也必须具有内存屏障?
没有人完全回答这个问题,所以我想我认为不需要内存屏障是正确的,但如果没有创建事先关系的东西,java编译器和热点可以进行优化(例如,吊装)将使它不做你想做的事.
问题是在多核系统上进行缓存 - 没有像volatile这样的事情会强制发生之前的关系(内存屏障的东西)你可以让你的编写器线程写入其核心缓存中的变量副本以及所有读取器线程读取另一个另一个核心上的变量副本.另一个问题是原子性,另一个答案解决了这个问题.
| 归档时间: |
|
| 查看次数: |
1017 次 |
| 最近记录: |