Почему это так фундаментально, что
каждый объект должен иметь их и
есть хит производительности в том, чтобы их
(предположительно некоторое состояние хранится в
их)?
tl; dr: Это методы обеспечения безопасности потоков и имеют небольшую стоимость по сравнению с их стоимостью.
Фундаментальные реальности, которые поддерживают эти методы , таковы:
- Java всегда многопоточная. Пример: посмотрите список потоков, используемых процессом, использующим jconsole или jvisualvm, когда-то.
- Правильность важнее, чем «производительность». Когда я оценивал проекты (много лет назад), мне приходилось объяснять, что «получить неправильный ответ очень быстро все еще неправильно».
По сути, эти методы предоставляют некоторые ловушки для управления мониторами для каждого объекта, используемыми при синхронизации. В частности, если у меня есть synchronized(objectWithMonitor)
в конкретном методе, я могу использовать objectWithMonitor.wait()
для выдачи этого монитора (например, если мне нужен другой метод для завершения вычисления, прежде чем я смогу продолжить). В этом случае это позволит еще одному заблокированному методу дождаться продолжения работы этого монитора.
С другой стороны, я могу использовать objectWithMonitor.notifyAll()
, чтобы сообщить темам, ожидающим монитор, о том, что я собираюсь вскоре отказаться от монитора. Они не могут продолжать, пока я не покину синхронизированный блок.
Что касается конкретных примеров (например, длинных списков двойных чисел), в которых вы можете беспокоиться о том, что в механизм мониторинга попала производительность или память, вот некоторые моменты, которые вам, вероятно, следует учитывать:
- Сначала докажи это. Если вы считаете, что основной механизм Java, такой как многопоточная корректность, оказывает серьезное влияние, есть отличный шанс, что ваша интуиция ложна. Измерьте воздействие в первую очередь. Если это серьезно, и вы знаете , что вам никогда не понадобится синхронизироваться на отдельном дубле, рассмотрите возможность использования пар вместо.
- Если вы не уверены, что вам, вашему коллеге, будущему программисту по техническому обслуживанию (который может стать самим собой через год) и т. Д., Никогда и никогда не понадобится когда-либо точная гранулярность theaded доступ к вашим данным, есть отличный шанс, что удаление этих мониторов сделает ваш код менее гибким и обслуживаемым.
Последующие действия в ответ на вопрос об объектах «на объект» и явных объектах монитора:
Краткий ответ: @JonSkeet: да, удаление мониторов создаст проблемы: это создаст трение. Хранение этих мониторов в Object
напоминает нам, что это всегда многопоточная система.
Встроенные мониторы объектов не сложны, но они просты в объяснении; работать предсказуемо; и ясно в их назначении. synchronized(this)
является четким заявлением о намерениях. Если мы заставляем начинающих кодеров использовать исключительно пакет параллелизма, мы вводим трение. Что в этом пакете? Что такое семафор? Вилочных присоединиться?
Начинающий кодер может использовать мониторы объектов для написания приличного кода модель-представление-контроллер. synchronized
, wait
и notifyAll
могут использоваться для реализации наивной (в смысле простой, доступной, но, возможно, не передовой) безопасности потоков. Каноническим примером может быть один из этих двойников (заданный OP), который может иметь один поток, устанавливающий значение, в то время как поток AWT получает значение для помещения его в JLabel. В этом случае нет веской причины для создания явного дополнительного объекта только для того, чтобы иметь внешний монитор.
При несколько более высоком уровне сложности эти же методы полезны в качестве метода внешнего мониторинга. В приведенном выше примере я это сделал явно (см. Фрагменты objectWithMonitor выше). Опять же, эти методы действительно удобны для создания относительно простой безопасности потоков.
Если вы хотите быть еще более изощренным, я думаю, вам следует серьезно подумать о прочтении Параллелизма Java на практике (если вы этого еще не сделали) Блокировки чтения и записи очень мощные, не добавляя слишком много дополнительной сложности.
Punchline: Используя базовые методы синхронизации, вы можете использовать большую часть производительности, обеспечиваемой современными многоядерными процессорами с поточной безопасностью и без лишних затрат.