я могу использовать синхронизировано с конечным полем?

Рассмотрим следующий код, я хочу сделать его потокобезопасным классом, чтобы он никогда не получал нечетное число:

class Test {
  private int value = 0;
  private final Object lock;

  public void add() {
    synchronized (lock) {
      value++;
      value++;
    }
  }

  public int getValue() {
    synchronized (lock) {
      return value;
    }
  } 
}

Теперь я сомневаюсь в поле блокировки, которое объявлено окончательным, будет ли это иметь значение? или это нарушит безопасность потока?

Я думаю, что если поле блокировки не объявлено окончательным, это должен быть потокобезопасный класс. Если этот вывод неверен, пожалуйста, поправьте меня, спасибо.


person alaska    schedule 13.07.2012    source источник
comment
См. этот вопрос.   -  person Lion    schedule 14.07.2012


Ответы (6)


Теперь я сомневаюсь в поле блокировки, которое объявлено окончательным, будет ли это иметь значение?

Да, рекомендуется только блокировать final объектов поля.

Если вы можете изменить ссылку, вы можете изменить, какой объект заблокирован, нарушив безопасность потоков.

person Peter Lawrey    schedule 13.07.2012

Должно быть хорошо. может даже сделать его более безопасным, поскольку нельзя просто присвоить блокировке что-то еще во время выполнения.

person Wug    schedule 13.07.2012

Вы можете использовать ReadWriteLock для достижения того же результата и с безопасной реализацией.

Использованная литература:

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReadWriteLock.html

http://www.javapractices.com/topic/TopicAction.do?Id=118

person Eduardo Andrade    schedule 13.07.2012

Если вы хотите заблокировать экземпляр, то final подходит. Если вы хотите заблокировать или поместить мьютекс в класс, сделайте переменную статической.

person Andreas    schedule 13.07.2012

В Java синхронизация выполняется некоторым скрытым полем объекта блокировки. Также final означает, что REFERENCE является final, а не сам объект.

Пример:

final Bar bar = new Bar(); //bar hase property lock
bar.lock = XYZ; //will work, object is not FINAL
bar = new Bar(); //fail, the reference is FINAL
person malejpavouk    schedule 13.07.2012
comment
Что бы это ни стоило, в Java нет встроенной конструкции, чтобы сделать «объекты окончательными». Неизменяемость должна обеспечиваться программно. - person corsiKa; 14.07.2012

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

Надеюсь, это имеет смысл; вам просто нужно синхронизировать на основе окончательной переменной, а не динамической.

Если метод изменяет статическое поле, вы должны синхронизировать доступ к этому полю, даже если метод обычно используется только одним потоком. Клиенты не могут выполнять внешнюю синхронизацию с помощью такого метода, потому что нет гарантии, что несвязанные клиенты будут делать то же самое, см..

person Lion    schedule 13.07.2012