Разъяснение по синхронизации - PullRequest
1 голос
/ 09 марта 2011

Допустим, у меня есть класс, у которого есть два метода calculateBonus(Account a) и calculatePenalty(Account a).

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

Штрафы и бонусы различны и сложны, возможно, чтоучетная запись может получить оба.Неважно, в каком порядке они рассчитываются (существует предельная дата, поэтому одно не влияет на результат другого), но крайне важно, чтобы я не пытался рассчитывать оба на одном и том же счете одновременно (для очевидных данныхИз соображений согласованности в каждом методе обновляются статусы и информация журнала аудита.

Как лучше всего спроектировать мой код, чтобы я мог БЕЗОПАСНО максимизировать параллельную обработку?

IДо сих пор рассматривали следующие варианты:

1) Поместите код, который рассчитывает бонусы и штрафы в разных классах, и используйте ключевое слово synchronized в методе.Не нравится эта идея, потому что есть некоторые общие сложные функции, которые я хотел бы сохранить вместе, они не связаны с вводом-выводом и выполняются быстро, поэтому не влияют на производительность.

2) Синхронизация на переданных в Account параметр.Если я правильно понимаю, это означает, что я не могу рассчитать бонус на другом счете, выполняющемся в другом потоке, пока бонус не будет рассчитан на первом счете в первом потоке.Но я мог бы рассчитать штраф для другого аккаунта в другом потоке - только не для аккаунта с тем же .Мне это нравится больше всего, но я хочу быть уверенным, что правильно его понимаю.

3) Создайте объект внутренней частной блокировки для каждого метода, который я хочу синхронизировать: один для бонусов и один для штрафов.Если вы правильно понимаете это, это означает, что только один поток может рассчитывать бонус за один раз, но это не не препятствует другому потоку рассчитывать штраф на тот же аккаунт в то же время.

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

1 Ответ

6 голосов
/ 09 марта 2011

Я думаю, что вариант 2 - или вариант на нем - ваш лучший выбор, но я думаю, что вы все еще немного неправильно его понимаете:

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

Нет - это означает, что:

  • Вы не сможете рассчитать ни бонус , ни штраф к той же учетной записи, поскольку ваша нить держит монитор для этой учетной записи.
  • Любая нить может рассчитать бонус или штраф на другой учетной записи, потому что у нее будет другой монитор.

Теперь обычно мне не нравится блокировка какой-либо общедоступной ссылки (такой как параметр Account), потому что это усложняет рассуждения о блокировке. Как правило, для каждого экземпляра Account предпочтительно иметь собственный объект, используемый только для блокировки, например,

private final Object lock = new Object();

и, например, методы в Account, чтобы заблокировать это ... но если вы не можете поместить методы в Account, вы не сможете этого сделать. Возможно, эти методы должны быть в Account хотя? Возможно, вам следует изменить ответственность - чтобы у вас было Account.calculateBonus(BonusFormula) и Account.calculatePenalty(PenaltyFormula) или что-то подобное?

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

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