У меня мало сомнений относительно синхронизированных блоков. Перед моими вопросами я хотел бы поделиться ответами из другого связанного сообщения Link for Answer to related question. Я цитирую Peter Lawrey из того же ответа.Нужно ли синхронизировать записи, если мы синхронизируем чтение?
-
синхронизируется обеспечивает вас есть согласованное представление данных. Это означает, что вы прочтете последнее значение, а другие кеши получат последнее значение . Кэши достаточно умны, чтобы разговаривать друг с другом через специальную шину (но это не то, что требуется JLS, но разрешено). Эта шина означает, что она не должна касаться основной памяти, чтобы получить согласованное представление .
-
Если вы используете только синхронизируется, то не нужно будет нестабильной. Volatile полезен, если у вас очень простая операция, для которой синхронизировано .
В связи с выше у меня есть три вопроса ниже:
Q1. Предположим, что в многопоточном приложении есть объект или примитивное поле экземпляра, которое считывается только в синхронизированном блоке (запись может происходить в каком-либо другом методе без синхронизации). Также синхронизированный блок определен на каком-то другом объекте. Является ли объявление его изменчивым (даже если оно считывается внутри только синхронизированного блока) имеет смысл?
Q2. Я понимаю, что значение состояний объекта, на котором выполнена Синхронизация, является последовательным. Я не уверен, что состояние других объектов и примитивных полей считывается сбоку в синхронизированном блоке. Предположите, что изменения сделаны без получения блокировки, но чтение выполняется путем получения блокировки. Содержит ли состояние всех объектов и значение всех примитивных полей внутри синхронизированного блока.?
Q3. [Обновить]: Будут ли считаться все поля, считываемые в синхронизированном блоке, из основной памяти независимо от того, что мы заблокировали? [ответил CKing]
У меня есть подготовленный ссылочный код для моих вопросов выше.
public class Test {
private SomeClass someObj;
private boolean isSomeFlag;
private Object lock = new Object();
public SomeClass getObject() {
return someObj;
}
public void setObject(SomeClass someObj) {
this.someObj = someObj;
}
public void executeSomeProcess(){
//some process...
}
// synchronized block is on a private someObj lock.
// inside the lock method does the value of isSomeFlag and state of someObj remain consistent?
public void someMethod(){
synchronized (lock) {
while(isSomeFlag){
executeSomeProcess();
}
if(someObj.isLogicToBePerformed()){
someObj.performSomeLogic();
}
}
}
// this is method without synchronization.
public void setSomeFlag(boolean isSomeFlag) {
this.isSomeFlag = isSomeFlag;
}
}
Я хотел бы быть приятным в этом, но это одна из тех вещей, где честность лучше всего работает. Если вы думаете о таких вещах, как «извлечения из памяти» во время разговора о JMM, вы этого не поняли и следует избегать параллелизма. Но код не указан неверно. – Voo
сделать 'isSomeFlag' volatile исправить это – ControlAltDel
@ Voo Я отредактировал мой вопрос, извините за использование слова памяти, я имел в виду согласованный .. –