Я буду голосовать за второй вариант. Классы вообще не должны быть потокобезопасными (и поэтому не должны быть внутренне синхронизированы). Безопасность требует времени и часто не нужна. Кроме того, вы часто получаете такие ситуации, как: if (list.isEmpty()) list.add(filler);
. Если оба метода синхронизируются внутри, это не делает ничего хорошего. Список может быть пустым при первом вызове и иметь 1 000 000 записей при вызове add
. Весь оператор должен быть синхронизирован, чтобы быть полезным.
В целом, для каждого класса вам необходимо решить, является ли он потокобезопасным или нет. Те, что не будут, будут быстрее и могут быть сделаны потокобезопасными вызывающим абонентом, которому, как и в приведенном выше экземпляре, может понадобиться некоторая гибкость в том, как они идут по нему. Кроме того, есть умные способы избежать любой необходимости синхронизации, например, ссылаться на класс из одного потока. Большинство классов Java Collections Framework не являются и не должны быть потокобезопасными. Безопасность резьбы обычно должна обрабатываться на высоком уровне, а не на низком уровне.
Время от времени вы получаете класс низкого уровня, который должен обрабатывать много потоков трафика, а затем вам нужен do нужен класс, который является потокобезопасным. Моим любимым примером является JavaConcurrentSkipListMap, который выполняет ту же работу, что и TreeMap. Я использую TreeMap 100 раз для каждого использования JCSLM, но когда мне это нужно, это спасатель. (Без этого я бы застрял с Java 1.4.)
Если вы :, сделайте класс потокобезопасным, сделайте что-нибудь помимо методов синхронизации. Вы можете заблокировать другие потоки, когда вам это не нужно. Кто-то еще может синхронизировать ваш класс и блокировать методы, которые не нужно блокировать. По крайней мере, синхронизировать внутренний объект, который существует исключительно для синхронизации. Еще лучше синхронизировать логические группы полей внутри вашего класса и размещать блоки синхронизации только там, где они вам нужны.
Есть и другие способы обеспечения безопасности потоков без синхронизации - неизменные объекты, сравнение и замена и т. Д. Кроме того, запуск других потоков, чтобы основной поток не блокировался, может избежать критических узких мест, даже если он добавляет к общей рабочей нагрузке вашего компьютера.
У меня есть Удача, в редких случаях, просто синхронизация каждого метода в классе. И я могу (намеренно) заблокировать все это просто путем синхронизации с классом. Это просто и безопасно, и не вредит, если класс легко используется. Но я иногда ошибаюсь в отношении использования класса и должен отказаться от него, когда моя программа зависает, используя только 2% процессора, несмотря на 4 гиперпотоковых ядра.
Возможно, я должен добавить, что большая часть моей работы была связана с критическим временем программным обеспечением. Но слишком большая синхронизация, даже без реальных взаимоблокировок, может сделать любую программу слишком медленной для любых целей. И если время не имеет значения, вы должны не использовать использовать несколько потоков.
Я согласен с этим.Чтобы написать потокобезопасную программу, суть решения - это «контекст» вашего дизайна. «Дизайн» - это правильный выбор из нескольких тактик. –