Подтвердить что ты не робот

Ключевое слово java synchronized, необходимое для примитивного метода getter/setter?

Я прочитал некоторый Java-код и нашел следующие функции:

synchronized void setConnected(boolean connected){
   this.connected = connected;
}

synchronized boolean isConnected(){
   return connected;
}

Интересно, имеет ли смысл синхронизация здесь, или просто автор не понимает необходимость синхронизованного ключевого слова?

Я бы предположил, что синхронизация здесь бесполезна. Или я ошибаюсь?

4b9b3361

Ответ 1

Ключевое слово synchronized - это один из способов обеспечения безопасности потоков. Остерегайтесь: там (путь) больше к потокобезопасности, чем взаимоблокировки, или отсутствующие обновления из-за двух потоков, увеличивающих int без синхронизации.

Рассмотрим следующий класс:

class Connection {
  private boolean connected; 
  synchronized void setConnected(boolean connected){
    this.connected = connected;
  }
  synchronized boolean isConnected(){
    return connected;
  }
}

Если несколько потоков совместно используют экземпляр Connection, а один поток вызывает setConnected(true), без synchronized возможно, что другие потоки продолжают видеть isConnected() == false. Ключевое слово synchronized гарантирует, что все потоки будут видеть текущее значение поля.

В более технических терминах ключевое слово synchronized обеспечивает барьер памяти (подсказка: google that).

Более подробно: каждая запись, сделанная перед выпуском монитора (т.е. перед тем, как оставить блок synchronized), будет гарантирована каждым чтением, сделанным после получения одного и того же монитора (т.е. после ввода блока синхронизации на том же объект). В Java есть что-то, называемое случается-раньше (подсказка: google that), что не так тривиально, как "я написал код в этом порядке, поэтому все будет выполнено в этом порядке". Использование synchronized - это способ установить связь между событиями и гарантировать, что потоки видят память, как вы ожидали бы от них.

Другим способом достижения тех же гарантий в этом случае было бы исключить ключевое слово synchronized и пометить поле volatile. Гарантии, предоставляемые volatile, заключаются в следующем: все записи, сделанные потоком, прежде чем волатильная запись гарантированно будет видна в потоке после последующего волатильного чтения того же поля.

Как последнее замечание, в этом конкретном случае было бы лучше использовать поле volatile вместо synchronized accessors, потому что оба подхода обеспечивают одинаковые гарантии, а подход volatile -field позволяет одновременный доступ к поле из разных потоков (что может повысить производительность, если версия synchronized имеет слишком много противоречий).

Ответ 2

Для предотвращения ошибок согласованности памяти необходима синхронизация, см. http://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html. Хотя в этом конкретном случае volatile было бы гораздо более эффективным решением

private volatile boolean connected;

void setConnected(boolean connected){
   this.connected = connected;
}

boolean isConnected(){
   return connected;
}

Ответ 3

Возможно, автор разработал код с многопоточным подходом. Это означает, что методы синхронизированы, и более одного потока не смогут одновременно обращаться к синхронизированному коду на одном экземпляре объекта.