Блокировки как инструмент для одновременного обмена данными и обеспечения согласованности имеют несколько реализаций на платформе JAVA (например, Synchronized, ReentrantLock и т. д.). Эти уже написанные блокировки обеспечивают удобство для нашей разработки, но конкретная природа и тип блокировок редко упоминаются. В этой серии статей будут проанализированы распространенные имена и характеристики блокировок в JAVA, чтобы ответить на ваши вопросы.
4. Реентерабельный замок:
В этой статье речь идет о реентерабельных блокировках в широком смысле, а не только о ReentrantLock в JAVA.
Реентерабельные блокировки, также называемые рекурсивными блокировками, означают, что после того, как внешняя функция того же потока получит блокировку, внутренняя рекурсивная функция все еще имеет код для получения блокировки, но на нее это не влияет.
В среде JAVA ReentrantLock и синхронизированные блокировки являются реентерабельными блокировками.
Вот примеры использования:
Скопируйте код кода следующим образом:
общедоступный класс Test реализует Runnable{
общедоступная синхронизированная недействительная функция get(){
System.out.println(Thread.currentThread().getId());
набор();
}
общедоступный синхронизированный недействительный набор () {
System.out.println(Thread.currentThread().getId());
}
@Override
общественный недействительный запуск () {
получать();
}
public static void main(String[] args) {
Тест ss=новый тест();
новый поток(СС).start();
новый поток(СС).start();
новый поток(СС).start();
}
}
Окончательные результаты обоих примеров верны, то есть один и тот же идентификатор потока выводится дважды подряд.
Результат следующий:
Скопируйте код кода следующим образом:
Ид: 8
Ид: 8
Ид: 10
Ид: 10
Ид: 9
Ид: 9
Самая большая роль реентерабельных блокировок — избежать взаимоблокировок.
Давайте возьмем спин-блокировку в качестве примера.
Скопируйте код кода следующим образом:
общественный класс SpinLock {
частный владелец AtomicReference<Thread> =new AtomicReference<>();
публичная недействительная блокировка(){
Текущий поток = Thread.currentThread();
while(!owner.compareAndSet(null, current)){
}
}
публичная недействительная разблокировка (){
Текущий поток = Thread.currentThread();
владелец.compareAndSet(текущий, ноль);
}
}
Для спин-локов:
1. Если один и тот же поток вызывает lock() дважды, это приведет к тому, что позиция блокировки будет вызвана во второй раз. Если возникает взаимоблокировка, это означает, что блокировка не является повторно входящей. (В функции блокировки вы должны проверить, является ли поток тем потоком, который получил блокировку)
2. Если проблема 1 решена, блокировка будет снята при первом вызове unlock(). На самом деле замок не должен открываться.
(Использование времени подсчета для статистики)
После модификации это выглядит следующим образом:
Скопируйте код кода следующим образом:
общественный класс SpinLock1 {
частный владелец AtomicReference<Thread> =new AtomicReference<>();
частный счетчик int = 0;
публичная недействительная блокировка(){
Текущий поток = Thread.currentThread();
если(текущий==владелец.get()) {
считать++;
возвращаться ;
}
while(!owner.compareAndSet(null, current)){
}
}
публичная недействительная разблокировка (){
Текущий поток = Thread.currentThread();
если(текущий==владелец.get()){
если(счет!=0){
считать--;
}еще{
владелец.compareAndSet(текущий, ноль);
}
}
}
}
Эта спин-блокировка является возвратной блокировкой.