Java内存屏障和可见性

时间:2019-04-11 20:17:54

标签: java concurrency thread-safety java.util.concurrent memory-barriers

我对触发内存屏障时发生的确切情况感到困惑,我认为这也用于获得与主内存的缓存一致性,但是我进行了测试,结果我认为是错误的。

我有2个线程,主线程和另一个线程,为简单起见,我将它们分别称为M和T。

情况1:完全符合我的预期

如果T正在等待NOT volatile共享变量,然后M更改了该值,则T可能不会看到更改(因为正在读取缓存),但是如果T激活了内存屏障,则缓存值将被更新为主内存和线程可以结束他的工作。

情况2:这不符合我的预期

注意:要创建此案例,您需要用threadAt.get();注释该行,并用//mainAt.get();将该行取消逗号

这种情况与第一种情况完全相同,但是内存屏障已在M中激活,我认为该内存屏障会将所有缓存与主内存一起上载,因此T会看到它,但事实并非如此,T陷入永远的循环。

有人可以解释一下这种记忆障碍的真实情况吗?

package aaa.testVisibility;

import java.util.concurrent.atomic.AtomicInteger;

class Worker implements Runnable {

    @Override
    public void run() {
        AtomicInteger threadAt = new AtomicInteger(0); //<-- Used for activating memory barrier later
        System.out.println("Waiting");
        while (!TestVisibility01.go) {
            threadAt.get(); // <-- memory barrier fired, COMMENT THIS LINE AND UNCOMMENT THE OTHER
        }
        System.out.println("Exiting thread");

    }
}

public class TestVisibility01 {

    public static boolean go = false;

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Worker());
        AtomicInteger mainAt = new AtomicInteger(0);
        t.start();
        System.out.println("Main thread sleep");
        Thread.sleep(2000);
        go = true;
        //mainAt.get(); // <-- memory barrier fired, UNCOMMENT THIS LINE AND COMMENT THE OTHER
        System.out.println("Main thread restart");
        t.join();
        System.out.println("Main exit");
    }
}

0 个答案:

没有答案