Барьер памяти Java и видимость - PullRequest
0 голосов
/ 11 апреля 2019

Я запутался в том, что происходит именно тогда, когда барьер памяти срабатывает, я думал, что это также используется для получения согласованности кэша с основной памятью, но я запустил тест и, как результат, то, что я считал неправильным.

У меня есть 2 потока, основной и другой, я буду называть их M и T для простоты.

Случай 1: Это работает точно так, как я ожидал

Если T ожидает переменную совместно изменяемой переменной, а затем M меняет это значение, вероятно, T не увидит эти изменения (потому что читает кэш), НО, если T активирует барьер памяти, тогда значение кэша обновляется с помощью Основная память и поток могут закончить свою работу.

Случай 2: Это не работает, как я ожидал

ПРИМЕЧАНИЕ: для создания этого CASE вам необходимо закомментировать строку с threadAt.get(); и снять с нее строку //mainAt.get();

Этот случай совершенно идентичен первому, НО барьер памяти активирован в М, я думал, что барьер памяти загрузит все кэши в основную память и, следовательно, 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");
    }
}
...