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