Я экспериментировал с проблемой видимости потока Java с популярным примером отправки сигнала остановки в поток с помощью общей логической и нелетучей переменной, и целевой поток, похоже, не получил ее) как показано ниже:Видимость и синхронизация потока Java
public class ThreadVisibilityTest {
//Shared variable to send a signal to the thread
static boolean stopped = false;
public static void main(String[] args) throws Exception {
Thread targetThread = new Thread(new Runnable() {
public void run() {
while(!stopped) {}
System.out.println("Target thread gets signal and stops...");
}
});
targetThread.start();
TimeUnit.SECONDS.sleep(5);
stopped=true;
System.out.println("Main thread has sent stop signal to the thread...");
}
}
Основной поток посылает сигнал остановки на целевой нити через 5 секунд с помощью установки stopped
к истинному и целевой поток не может получить его и так не прекращается.
stopped
переменный как volatile
, очевидно, решает проблему.
Бу-то я понял, что если я stopped
переменную non volatile
, но вместо того, чтобы получить доступ к нему в synchronized
контексте в целевом потоке, целевой поток получает окончательное значение и останавливается. Поэтому проблема видимости потока, похоже, решена так же, как с использованием volatile
.
Thread targetThread = new Thread(new Runnable() {
public void run() {
while(true) {
synchronized(this) {
if(stopped) break;
}
}
System.out.println("Target thread gets signal and stops...");
}
});
А также монитор объекта, который будет использоваться для синхронизации, кажется, не имеет никакого эффекта следующим образом:
synchronized(Thread.class) {
if(stopped) break;
}
Является ли это то, что происходит случайно или я что-то пропустил? Или можно сказать, что доступ к общей переменной с взаимным исключением, по-видимому, заставляет целевой поток обновлять свою кэш-память так же, как доступ к переменной volatile
?
Если последнее верно, в каком направлении вы предлагаете преодолеть проблему видимости потоков, используя ключевое слово volatile или доступ с взаимным исключением?
Заранее спасибо
Если вы знаете, что нужно использовать самое последнее значение этой переменной, почему бы вам не использовать volatile? Что вы видите в этом как проблема? –
Если вы хотите использовать синхронизацию, вам обязательно нужно выполнить запись и чтение остановленных в блоках, синхронизированных на одном мониторе. Вы не записываете значение в синхронизированный блок. –
Я не собираюсь выбирать нестабильность.Я просто пытаюсь понять, почему взаимное исключение также решает проблему видимости памяти, как я протестировал, и видел, что доступ к общей переменной с взаимным исключением заставляет вас получить свое окончательное значение так же, как volatile. – Serdar