Из документации Condition
:
Condition
исключает Object
методы мониторинга (wait
, notify
и notifyAll
)в отдельные объекты, чтобы получить эффект наличия нескольких наборов ожидания на объект, комбинируя их с использованием произвольных Lock
реализаций. Где Lock
заменяет использование synchronized
методов и операторов, Condition
заменяет использование Object
методов монитора.
Условия (также известные как очереди условий или переменные условия) предоставляет способ для одного потока приостановить выполнение («подождать») до тех пор, пока другой поток не уведомит о том, что какое-то условие состояния теперь может выполнятьсяПоскольку доступ к этой информации общего состояния происходит в разных потоках, она должна быть защищена, поэтому блокировка некоторой формы связана с условием. Ключевое свойство, которое обеспечивает ожидание условия, заключается в том, что оно атомарно снимает связанную блокировку и приостанавливает текущий поток, так же как Object.wait
.
A Condition
экземпляр по своей природе связан сзамок. Чтобы получить экземпляр Condition
для конкретного экземпляра Lock
, используйте его метод newCondition()
.
Как объяснено, Condition
экземпляр должен быть связан с Lock
экземпляром 1 . Наличие Lock
в качестве фабрики для создания экземпляров Condition
имеет смысл с учетом этого, поскольку подразумевает взаимосвязь между ними. Другой способ, которым это соотношение могло бы быть реализовано, - дать Condition
конструктор, который принимает экземпляр Lock
, но , поскольку Condition
также является интерфейсом , который не может объявлять конструкторы. Я также считаю, что метод фабрики без аргументов в этом случае более удобен для пользователя.
Примечание: Если это еще не ясно, ReentrantLock
класс является реализацией интерфейса Lock
, а класс ConditionObject
является реализацией интерфейса Condition
.
Другая проблема при попытке использовать ConditionObject
напрямую заключается в том, что этовнутренний класс (т. е. нестатический вложенный класс) AbstractQueuedSynchronizer
2 . Это означает, что вам понадобится экземпляр последнего класса, чтобы создать экземпляр первого класса. Однако реализация AbstractQueuedSynchronizer
, используемая ReentrantLock
, представляет собой подробность реализации и не доступна широкой публике. Другими словами, у вас нет возможности вызвать конструктор ConditionObject
, что означает, что единственный способ создания экземпляра - это newCondition()
.
Напомним, что существует как минимум три причины, по которым метод фабрикииспользуется для создания Condition
объектов:
- Это делает связь между
Lock
и Condition
ясной. - Поскольку интерфейсы
Lock
и Condition
являютсянужен способ связать Condition
с Lock
, не зная о реализациях. В противном случае было бы невозможно «программировать на интерфейс» . - Поскольку
ConditionObject
является внутренним классом, его нельзя создать напрямую - по крайней мере, не с помощью кода, который не 'у него нет доступа к экземпляру включающего класса.
1. Методы Condition
имеют смысл только в контексте владения Lock
. Точно так же, как поток должен быть synchronized
для объекта, прежде чем он сможет законно вызывать методы монитора этого объекта (например, wait / notify), поток должен владеть ассоциированным Lock
, прежде чем он сможет законно вызывать методы Condition
(т.е. ожидание / сигнал).
2. Также есть AbstractQueuedLongSynchronizer
, который объявляет свой собственный ConditionObject
внутренний класс. Хотя имя класса совпадает с именем, объявленным AbstractQueuedSynchronizer
, оба фактически являются отдельными классами.