Я читаю «Общие сведения о расширенных возможностях и передовой практике JVM», в которых есть сегмент кода, который объясняет, - до правила в java. Я не могу понять. Код ниже:если поток A начинается до потока B в java, тогда A будет назначаться os до B?
private int value = 0;
//executed by Thread A
public void setValue(int value){
this.value = value;
}
//executed by Thread B
public void getValue(){
return value;
}
Предположим, что нить A
начинается до резьбы B
в коде. Я могу понять, что мы не знаем результат, возвращенный getValue()
в Thread B, потому что он не является потокобезопасным. Но в книге говорится, что если добавить синхронизированное ключевое слово для функции setValue()
и getValue()
, тогда нет проблемы с потоком, и метод getValue()
вернет правильное значение. В книге объясняется, что, поскольку synchronized
встречается с правилом «бывает раньше». Таким образом, у меня есть два вопроса ниже кода.
public class VolatileDemo3 {
private volatile int value = 0;
public static void main(String[] args) {
VolatileDemo3 v = new VolatileDemo3();
Thread A = new Thread(v.new Test1());// Thread A
Thread B = new Thread(v.new Test2());//Thread B
A.start();
B.start();
}
public void setValue(int value){
this.value = value;
}
public int getValue(){
return this.value;
}
public class Test1 implements Runnable {
@Override
public void run() {
setValue(10);
}
}
public class Test2 implements Runnable {
@Override
public void run() {
int v = getValue();
System.out.println(v);
}
}
}
- Хотя
A.start()
пробег перед темB.start()
и значением являетсяvolatile
, мы не можем обеспечить поток B может распечатать10
, верно? Поскольку нить B возможно планируется сначала JVM, то поток B напечатает 0 не 10. - Даже если нить
A
планируется провести до резьбыB
на JVM, но мы также не можем гарантировать, что командаthis.value = value
выполняется JVM, прежде чемreturn this.value
потому что JVM снова сортирует инструкции. Правильно ли я понимаю? Пожалуйста, помогите мне.
Существует различие между «безопасным потоком» и «предсказуемым». Добавление 'synchronized' будет означать, что Thread B всегда будет видеть _correct_' значение', но он, возможно, еще не был обновлен. Как вы заметили, нет гарантии, что два потока будут выполняться в предполагаемом порядке. Без 'synchronized' не существует _visibility warranty_, поэтому даже если A выполняется первым, B все еще может видеть старое значение. –
Я думаю, что вы неправильно читаете. Если есть ключевое слово «synchronized», это означает, что JVM гарантирует, что в любой данный момент вы не сможете одновременно выполнять два потока, выполняющих одновременно «setValue» и «getValue» (каждый из них должен завершить выполнение своего метода до другой поток может ввести другой метод). Он не * ничего не гарантирует о порядке этих операций. – Paolo
Чтобы обеспечить «правильную» видимость, вы должны объявить 'private volatile int value = 0;'. Это заставляет задуматься, что написанное значение увидено всеми остальными потоками после. – PeterMmm