Я хотел бы связать приведенное выше утверждение с некоторым примером потока кода.
Чтобы понять это, давайте возьмем ниже класс, который имеет два поля counter
и isActive
.
class StateHolder {
private int counter = 100;
private boolean isActive = false;
public synchronized void resetCounter() {
counter = 0;
isActive = true;
}
public synchronized void printStateWithLock() {
System.out.println("Counter : " + counter);
System.out.println("IsActive : " + isActive);
}
public void printStateWithNoLock() {
System.out.println("Counter : " + counter);
System.out.println("IsActive : " + isActive);
}
}
И предположим, что есть три потока T1, T2, T3, вызывающие следующие методы для одного и того же объекта StateHolder
:
T1 вызывает resetCounter()
, а T2 вызывает printStateWithLock()
одновременно, и T1 получает блокировку
T3 -> вызывает printStateWithNoLock()
после того, как T1 завершил свое выполнение.
Следует отметить, что наличие отношения «происходит до» между двумя действиями не обязательно означает, что они должны выполняться в этом порядке в реализации. Если изменение порядка приводит к результатам, согласующимся с законным исполнением, оно не является незаконным.
и непосредственная линия говорит,
Согласно приведенному выше утверждению, это дает возможность JVM, ОС или базовому оборудованию изменять порядок операторов в методе resetCounter()
. И по мере выполнения T1 он может выполнять операторы в следующем порядке.
public synchronized void resetCounter() {
isActive = true;
counter = 0;
}
Это соответствует утверждению не обязательно означает, что они должны выполняться именно в таком порядке в реализации.
Теперь, если посмотреть на это с точки зрения T2, это переупорядочивание не имеет негативного влияния, потому что и T1, и T2 синхронизируются с одним и тем же объектом, и T2 гарантированно увидит изменения в обоих полях, независимо от того, было ли переупорядочение случилось или нет, как там бывает-прежде отношения. Таким образом, вывод всегда будет:
Counter : 0
IsActive : true
Это соответствует утверждению: Если изменение порядка приводит к результатам, согласующимся с законным исполнением, оно не является незаконным.
Но посмотрите на это с точки зрения T3, при таком переупорядочении возможно, что T3 увидит обновленное значение isActive
как «truebut still see the
countervalue as
100», хотя T1 завершил свое выполнение.
Counter : 100
IsActive : true
Следующий пункт в приведенной выше ссылке дополнительно разъясняет утверждение и говорит, что:
Более конкретно, если два действия имеют общую связь «происходит до», они не обязательно должны казаться произошедшими в этом порядке для любого кода, с которым они не имеют общей связи «произошло до». Записи в одном потоке, которые находятся в гонке данных с чтением в другом потоке, могут, например, казаться происходящими не по порядку для этих чтений.
В этом примере T3 столкнулся с этой проблемой, так как она не имеет отношения «происходит до» с T1 или T2. Это встроено в Не обязательно должно казаться, что это произошло в этом порядке для любого кода, с которым они не имеют общего отношения "происходит до".
ПРИМЕЧАНИЕ. Для упрощения случая у нас есть один поток T1, изменяющий состояние, и T2 и T3, считывающие состояние. можно иметь
T1 обновляет counter to 0
, позже
T2 изменяет isActive на true
и видит counter is 0
, через некоторое время
T3, который печатает состояние, все еще может видеть only isActive as true but counter is 100
, хотя и T1, и T2 завершили выполнение.
Что касается последнего вопроса:
у нас есть hb(w, r), но это не значит, что c будет содержать значение 3 после присваивания. Как обеспечить, чтобы c присваивалось значение 3?
public volatile int v;
public int c;
Thread A
v = 3; //w
Thread B
c = v; //r
Поскольку v
является изменчивым, согласно Происходит перед заказом
Запись в изменчивое поле (§8.3.1.4) происходит перед каждым последующим чтением этого поля.
Таким образом, можно с уверенностью предположить, что когда поток B пытается прочитать переменную v
, он всегда будет читать обновленное значение, а c
будет присвоено значение 3 в приведенном выше коде.
person
Madhusudana Reddy Sunnapu
schedule
03.04.2016