0. О мутекс
Так называемая блокировка Mutex относится к блокировке, который может иметь только одну нить за раз. Перед JDK1.5 мы обычно использовали синхронизированный механизм для контроля доступа нескольких потоков к общим ресурсам. Теперь Lock обеспечивает более широкий диапазон операций блокировки, чем синхронизированный механизм. Основные различия между блокировками и синхронизированными механизмами:
Синхронизированный механизм обеспечивает доступ к неявным замкам монитора, связанным с каждым объектом, и заставляет все снимать и высвобождение блокировки в структуре блока. Когда получается несколько замков, они должны быть выпущены в обратном порядке. Синхронизированный механизм неявно выделяет замки. Пока код запускается по потоку превышает объем блока синхронизированного оператора, блокировка будет выпущена. Механизм блокировки должен явно вызвать метод разблокировки () объекта блокировки, чтобы освободить блокировку, что дает возможность для сбора и освобождения блокировки не отображаться в той же структуре блока, и освободить блокировки в более свободном порядке.
1. Введение в повторный зал.
Reentrantlock - это замок Mutex Reentrant, также известный как «эксклюзивный замок».
Как следует из названия, блокировка повторного блока может быть удерживана только одним блокировкой резьбы в одно и то же время; В то время как Reentrant означает, что блокировку повторного блока может быть получена несколько раз одним потоком.
Reentrantlock разделен на «честный замок» и «несправедливый замок». Их различия отражаются в том, является ли механизм получения замков справедливым. «Lock» - это защита конкурирующих ресурсов и предотвращение эксплуатационных потоков несколько потоков одновременно и ошибок. Reentrantlock может быть получен только одним потоком одновременно (когда нить приобретает «блокировка», другие потоки должны ждать); Reentraantlock управляет всеми нитями, которые приобретают замок через очередь ожидания FIFO. Под механизмом «Справедливой блокировки» нить очередь, чтобы получить блокировку в последовательности; в то время как «не-Fair Lock» приобретет замок независимо от того, находится ли он в начале очереди или нет.
Список функций повторного залога
// Создать повторный зал, который по умолчанию является «несправедливой блокировкой». Reentrantlock () // Политика создания - это ярмарка. Если справедливо верно, это означает, что это справедливая блокировка, и если справедливо неверно, это означает, что это не FIAR Bock. Reentrantlock (логическая ярмарка) // Запрос, сколько раз, когда текущий поток поддерживал этот замок. int getholdCount () // Возвращает поток, который в настоящее время владеет этой блокировкой, и если эта блокировка не принадлежит нику, верните NULL. Защищенная потока GetOwner () // Возвращает коллекцию, содержащую поток, которая может ждать, чтобы приобрести этот замок. Защищенная коллекция <Тема> getQueuedThreads () // Возвращает предполагаемое количество потоков, ожидающих, чтобы приобрести этот замок. int getQueueldethen () // Возвращает коллекцию, которая содержит те потоки, которые могут ждать данного условия, связанного с этим блоком. Защищенная коллекция <потока> getWaitingThreads (условие условия) // Возвращает оценку потока в ожидании заданного условия, связанного с этим блоком. int getwaitqueueldength (условие условия) // Запрос, ждет ли данная поток, чтобы приобрести этот замок. Boolean HasqueuedThread (потока потока) // Запрос, ожидают ли некоторые потоки, чтобы получить этот замок. Boolean hasqueuedThreads () // Запрашивает, ждут ли некоторые потоки заданное условие, связанное с этим замком. Boolean Haswaitters (условие условия) // вернуть true, если это «справедливая блокировка», в противном случае вернуть ложь. Boolean Isfair () // Запрос, поддерживает ли текущий поток этот блокировка. Boolean IsheldbycurrentThread () // Запрос, удерживается ли этот блокировка любым потоком. Boolean Islocked () // Получить замок. void lock () // Если текущий поток не прерывается, блокировка получена. void LockErruptable () // Возвращает экземпляр условия, используемый для использования с этим экземпляром блокировки. Условие NewCondition () // Приобретение блокировки только в том случае, если он не удерживается другим потоком во время вызова. Boolean Trylock () // Если блокировка не удерживается другим потоком в течение данного времени ожидания, а текущий поток не прерывается, блокировка получена. Boolean Trylock (Long Timeout, TimeUnit Unit) // Попытка выпустить этот замок. void unlock ()
2. Reentrantlock Пример
Сравнивая «Пример 1» и «Пример 2», мы можем четко понять роль блокировки и разблокировки
2.1 Пример 1
Import java.util.concurrent.locks.lock; import java.util.concurrent.locks.reentrantlock; // locktest1.java// Repository Class Depot {private int size; // фактическое количество репозитория частного блокировки блокировки; // Exclusive Lock Public Depot () {this.Size = 0; this.lock = new Reentrantlock (); } public void продукт (int val) {lock.lock (); try {size += val; System.out.printf ("%s Производство (%d) -> size =%d/n", thread.currentThread (). GetName (), val, size); } наконец {lock.unlock (); }} public void потребление (int val) {lock.lock (); попробуйте {size -= val; System.out.printf ("%s потребление (%d) <- size =%d/n", thread.currentthread (). GetName (), val, size); } наконец {lock.unlock (); }}}; // Производитель продюсер {Private Depot Deposit; Public Producer (Depot Depot) {this.depot = dephit; } // потребительские продукты: Создайте новую ветку для производства продуктов на складе. public void Produce (final int val) {new Thread () {public void run () {depoit.produce (val); } }.начинать(); }} // Consumer Class Customer {Private Depot Deposit; Общественный клиент (депо) {this.depot = депозит; } // потребительский продукт: Создайте новую ветку для потребления продукта со склада. public void потребление (final int val) {new Thread () {public void run () {depot.consume (val); } }.начинать(); }} public class locktest1 {public static void main (string [] args) {depot mdepot = new Depot (); Производитель MPRO = новый производитель (MDEPOT); MCUS = новый клиент (MDEPOT); MPRO.Produce (60); MPRO.Produce (120); mcus.consume (90); mcus.consume (150); MPRO.Produce (110); }} Результаты работы:
Поток Thread-0 (60)-> размер = 60thread-1 Производство (120)-> Размер = 180thread-3 потребление (150) <-size = 30thread-2 потребление (90) <-size = -60thread-4 Производство (110)-> Размер = 50
Анализ результатов:
(1) Депо является складом. Товары могут быть произведены на склад через продукт (), а товары на складе могут использоваться посредством потребления (). Взаимно эксклюзивный доступ к складу достигается за счет эксклюзивной блокировки: перед эксплуатацией товаров на складе (производство/потребление) склад сначала будет заблокирован через Lock (), а затем разблокирован через разблокировку () после завершения операции.
(2) Производитель является производителем. Вызов функции продукта () в производителе может создать новый поток для производства продуктов на складе.
(3) Клиент - это потребительская категория. Вызов функции потребления () в клиенте может создать новый продукт потребления потока на складе.
(4) В главной теме поток мы создадим нового производителя MPRO и новых потребительских MCU. Они производят/потребительские продукты в склады соответственно.
Согласно количеству производства/потребления в основном, конечный оставшийся продукт на складе должен составлять 50. Результаты операции соответствуют нашим ожиданиям!
Есть две проблемы с этой моделью:
(1) В действительности способность склада не может быть отрицательной. Тем не менее, способность склада в этой модели может быть отрицательной, что противоречит реальности!
(2) В действительности способность склада ограничена. Тем не менее, в этой модели действительно нет ограничений!
Мы кратко поговорим о том, как решить эти две проблемы. Теперь давайте сначала посмотрим на простой пример 2; Сравнивая «Пример 1» и «Пример 2», мы можем более четко понять цель Lock () и разблокировать ().
2.2 Пример 2
Import java.util.concurrent.locks.lock; import java.util.concurrent.locks.reentrantlock; // locktest2.java// Repository Class Depot {private int size; // фактическое количество репозитория частного блокировки блокировки; // Exclusive Lock Public Depot () {this.Size = 0; this.lock = new Reentrantlock (); } public void продукт (int val) {// lock.lock (); // try {size += val; System.out.printf ("%s производит (%d) -> size =%d/n", thread.currentThread (). GetName (), val, size); //} catch (urrupteDexception e) {//} наконец {// lock.unlock (); //}} public void emance (int val) {/ lock.clock (); //}} public void (int val) {/ lock.lock (); System.out.printf ("%s потребление (%d) <- size =%d/n", thread.currentThread (). GetName (), val, size); //} наконец {// lock.unlock (); //}}}; // Производитель производителя класса. Public Producer (депозит) {this.depot = депозит; } // потребительский продукт: Создайте новую ветку для производства продукта на складе. public void Produce (final int val) {new Thread () {public void run () {depoit.produce (val); } }.начинать(); }} // Consumer Class Customer {Private Depot Deposit; Общественный клиент (депо) {this.depot = депозит; } // потребительский продукт: Создайте новую ветку для потребления продукта со склада. public void потребление (final int val) {new Thread () {public void run () {depot.consume (val); } }.начинать(); }} public class locktest2 {public static void main (string [] args) {depot mdepot = new Depot (); Производитель MPRO = новый производитель (MDEPOT); MCUS = новый клиент (MDEPOT); MPRO.Produce (60); MPRO.Produce (120); mcus.consume (90); mcus.consume (150); MPRO.Produce (110); }} (Один раз) Результат:
Поток Thread-0 (60)-> size = -60thread-4 Производство (110)-> Размер = 50thread-2 Потребление (90) <-size = -60thread-1 Производство (120)-> Размер = -60thread-3 Потребление (150) <-size = -60
Результаты Описание:
«Пример 2» удаляет блокировку блокировки на основе «Пример 1». В примере 2 окончательный оставшийся продукт на складе составляет -60, а не 50, которые мы ожидали. Причина в том, что мы не реализуем Mutex доступ к репозиторию.
2.3 Пример 3
В «Примере 3» мы используем условие для решения двух задач в «Примере 1»: «способность склада не может быть отрицательной», а «способность склада ограничена».
Решение этой проблемы - через состояние. Условие должно использоваться в сочетании с блокировкой: метод wait () в условии может привести к блокированию потока [аналогично wait ()]; Метод состояния сигнала () может привести к тому, что поток для пробуждения [аналогично notify ()].
Import java.util.concurrent.locks.lock; import java.util.concurrent.locks.reentrantlock; import java.util.concurrent.locks.condition; // locktest3.java// Class Depot {Private Int; // Собственная емкость частный размер int; // фактическое количество склада частного блокировки блокировки; // Эксклюзивное блокировка частного условия Fullcondition; // Производственные условия частное состояние пустое кондиционирование; // Условия потребления Public Depot (int емкость) {this.capacity = емкость; this.size = 0; this.lock = new Reentrantlock (); this.fullCondtion = lock.newCondition (); this.emptyCondition = lock.newCondition (); } public void продукт (int val) {lock.lock (); Попробуйте {// левое означает «количество, которое вы хотите произвести» (это может быть слишком много производства, поэтому вам нужно создать больше) int Left = val; В то время как (слева> 0) {// Когда инвентарь заполнен, подождите, пока «потребитель» потребляет продукт. while (size> = емкость) fullcondtion.await (); // Получить «фактическое количество производства» (то есть новое количество, добавленное в инвентаризации) // Если «инвентарь» + «желаемое количество производства»> «Общая мощность», то «фактическое увеличение» = «Общая мощность» - «текущая мощность». (Заполните склад в это время) // В противном случае «Фактический приращение» = «Количество, которое вы хотите произвести« int inc = (размер+слева)> емкость? (размер емкости): слева; размер += Inc; слева -= Inc; System.out.printf ("%s продукт (%3d) -> слева =%3d, inc =%3d, size =%3d/n", thread.currentThread (). GetName (), val, left, inc, size); // Уведомление «потребителя», которого вы можете потреблять. EmptyCondtion.Signal (); }} catch (прерывание Exception e) {} наконец {lock.unlock (); }} public void потребление (int val) {lock.lock (); Попробуйте {// левое означает «количество потребления, которое нужно потреблять» (он может быть слишком большим, инвентарь недостаточно, поэтому вам нужно потреблять больше) int left = val; В то время как (слева> 0) {// Когда инвентарь равен 0, подождите, пока «продюсер» произведет продукт. while (size <= 0) EmptyCondtion.await (); // Получить «фактическое количество потребления» (то есть фактическое уменьшение инвентаря) // Если «инвентарь» <», которую клиент хочет потреблять», то «фактическое потребление» = «инвентарь»; // в противном случае «фактическое потребление» = «количество, которое клиент хочет потреблять». int dec = (размер <слева)? размер: слева; размер -= dec; слева -= dec; System.out.printf ("%s потребление (%3d) <- слева =%3d, dec =%3d, size =%3d/n", thread.currentThread (). GetName (), val, слева, dec, размер); FullCondtion.Signal (); }} catch (прерывание Exception e) {} наконец {lock.unlock (); }} public String toString () {return "емкость:"+емкость+", фактический размер:"+size; }}; // Производитель Class Produce {Private Depot Deposit; Public Producer (депозит) {this.depot = депозит; } // потребительский продукт: Создайте новую ветку для производства продукта на складе. public void Produce (final int val) {new Thread () {public void run () {depoit.produce (val); } }.начинать(); }} // Consumer Class Customer {Private Depot Deposit; Общественный клиент (депо) {this.depot = депозит; } // потребительский продукт: Создайте новую ветку для потребления продукта со склада. public void потребление (final int val) {new Thread () {public void run () {depot.consume (val); } }.начинать(); }} public class locktest3 {public static void main (string [] args) {depot mdepot = new Depot (100); Производитель MPRO = новый производитель (MDEPOT); MCUS = новый клиент (MDEPOT); MPRO.Produce (60); MPRO.Produce (120); mcus.consume (90); mcus.consume (150); MPRO.Produce (110); }} (Один раз) Результат:
Продукт потока-0 (60)-> левый = 0, Inc = 60, размер = 60thread-1 продукт (120)-> слева = 80, Inc = 40, размер = 100thread-2 Потребление (90) <-слева = 0, декабрь = 90, размер = 10thread-3 Потребление (150) <-слева = 140, размер 10, размер = 0thread-4. Потребление (150) <-слева = 40, декабрь = 100, размер = 0thread-4 Производство (110)-> левое = 0, Inc = 10, размер = 10thread-3 потребление (150) <-слева = 30, декабрь = 10, размер = 0thread-1 (120)-> слева = 0, INC = 80, размер = 80-й читатель-3 потребляемый (150) <-левый = 0, 30, 30 декабря = 30 декабря = 30, 30 декабрь = 50, 30-й.