Джава. Как правильно синхронизировать геттеры и сеттеры? - PullRequest
10 голосов
/ 19 июня 2010

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

class Doggie {
    private String name;
    private int    age;

    public void setName(String name) { this.name = name; }
    public String getName() { return this.name; }
    public void setAge(int age) { this.age = age; }
    public int getAge() { return this.age; }

}

Вопросы:

  • Не являютсяreturn и атомарные операции присваивания в Java?
  • Поскольку свойства не обязательно взаимосвязаны, не всегда имеет смысл синхронизировать с одной и той же блокировкой.Как организовать структуру блокировки?
  • Лучше пойти с внутренней блокировкой или с шаблоном частной блокировки объекта?

Ответы [ 5 ]

10 голосов
/ 19 июня 2010
  • Не являются ли атомарные операции возврата и присваивания в Java?

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

  • Когда чтенияи записи находятся в одном потоке, чтение гарантированно увидит более раннюю запись.

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

Обратите внимание, что примитивные блокировки / мьютексы - не единственный способ синхронизации.

  • Поскольку свойства не обязательно взаимосвязаны, не всегда имеет смысл синхронизировать с одной и той же блокировкой.Как организовать структуру блокировки?

Имеет смысл использовать несколько блокировок, если (и только если) вероятен конфликт блокировок.В вашем примере проблема блокировки может возникнуть только в том случае, если какой-либо экземпляр Doggie получает очень высокую скорость операций get и / или set.

  • Лучше использоватьвстроенная блокировка или шаблон блокировки закрытого объекта?

Зависит от этого.Если ваше приложение будет использовать примитивную блокировку объекта Doggie, то вы можете получить конфликт блокировки или даже непреднамеренную блокировку операций get и set.В этом случае частная блокировка может быть целесообразной.В противном случае частная блокировка - это ненужные накладные расходы.

5 голосов
/ 19 июня 2010

Ваш пример просит неизменного объекта. http://java.sun.com/docs/books/tutorial/essential/concurrency/imstrat.html

3 голосов
/ 19 июня 2010

Операции со ссылками являются атомарными, но не изменчивыми - вы всегда увидите старое или новое значение, но нет гарантии, что вы увидите новое значение без какого-либо барьера памяти. Я не могу вспомнить детали того, какие примитивы гарантированно будут атомарными - возможно, только длинные и двойные.

Лично я бы использовал один закрытый замок, пока не увидел никаких доказательств того, что это узкое место. Я бы посоветовал не блокировать «this», так как другой код может также заблокировать его. Если вы единственный код, который знает о блокировке, получить помехи будет сложнее. Сказав это, если вызывающие хотят атомарно изменить более одного свойства, вы можете захотеть выставить блокировку через свойство.

Вам определенно нужен потокобезопасный изменяемый тип? Если бы вы могли избежать этого требования, это сделало бы жизнь проще.

1 голос
/ 19 июня 2010
  • Это атомарные операции, но представьте себе сценарий, в котором два клиента пытаются получить и задать часть данных одновременно.Нет никаких гарантий относительно того, какие заказы будут вызываться, что может значительно повлиять на результаты вашего заявления.(Классический пример - денежные транзакции.)
  • Может иметь или не иметь смысл синхронизировать с одной и той же блокировкой - это действительно зависит от вашего приложения.Однако, как правило, не стоит блокировать весь объект, если в этом нет необходимости.
  • Как и в случае с тем, что сказал Джон, начните с одной частной блокировки и переходите оттуда в зависимости от результатов.
0 голосов
/ 19 июня 2010

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

Облегченный способ сделать это - просто установить логическое значение, установленное во время работы свойстванаписано и ясно, иначе.Тяжелый способ сделать это, поддержать тайм-ауты и т. Д. С помощью мьютекса.

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