Синхронизированное чтение свойства как несинхронизированное свойство
У меня есть неатомарное свойство Java, которое может быть установлено синхронизированным установщиком. У меня вопрос, могу ли я прочитать это свойство несинхронизированным геттером? Благодарю.
4 ответа
Если свойство не является атомарным, вам, возможно, придется ввести ReadwriteLock. См. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReadWriteLock.html
Вы можете прочитать свойство, то есть поток увидит какое-то значение, но проблема в том, что оно непредсказуемо - оно может не отражать самое последнее значение, записанное другим потоком, или оно может быть даже случайным значением. Следовательно, вам также следует синхронизировать геттер. Не безопасно синхронизировать только методы, которые пишут в переменную.
Ответ зависит от того, является ли поле изменчивым.
Если поле не является изменчивым, то остальные ответы верны. Вы можете прочитать значение, но поток, выполняющий чтение, не сможет "увидеть" значение, которое написал другой поток. Записанное значение может находиться в локальном кеше потока, поэтому второй поток всегда может увидеть старое значение. Кроме того, JIT-компилятор может свободно переупорядочивать код так, чтобы он работал, только если никто не читает значение одновременно.
Если поле изменчиво, то вы получите поведение, которое хотите. JVM гарантирует, что каждый поток получит последнее значение.
Обратите внимание, что вы не должны выполнять операции чтения-изменения-записи (например, увеличение целочисленного поля) над изменяемым полем вне синхронизированного блока, поскольку условия гонки могут привести к неожиданным результатам.
Для более подробной информации читайте Java Concurrency in Practice.
Вы можете прочитать значение с помощью метода getter, но вы можете получить непредсказуемое значение. Поскольку при перемещении вы получаете значение от получателя, возможно, что другой поток вызовет метод установщика и изменит значение. Поэтому, чтобы избежать нарушения данных, мы должны синхронизировать setter и getter, и он должен быть заблокирован под одной и той же блокировкой объекта.