Java 5.0 이전에는 동기화(내장 잠금) 및 휘발성만 있었습니다. Java 5.0 이후에는 디스플레이 잠금 ReentrantLock이 도입되었습니다.
재진입 잠금 개요
ReentrantLock은 내장된 잠금과는 다르며, 사용할 때마다 명시적인 잠금 및 잠금 해제가 필요하며 공정 잠금, 시간 제한 잠금, 조건부 잠금, 인터럽트 가능 잠금 등의 고급 기능을 제공합니다. ReentrantLock 구현의 활성 문제를 효과적으로 피할 수 있습니다.
잠금 인터페이스:
다음과 같이 코드 코드를 복사합니다.
공개 인터페이스 잠금 {
//잠금을 얻거나 중단될 때까지 차단합니다.
무효 잠금();
//인터럽트 시 잠금을 얻거나 예외가 발생할 때까지 차단합니다.
void lockInterruptously()는 InterruptedException을 발생시킵니다.
//잠금이 사용 가능한 경우에만 획득하고, 그렇지 않으면 직접 반환
부울 tryLock();
//지정된 시간 내에 사용 가능한 경우에만 잠금을 획득하고, 그렇지 않으면 직접 반환하고 중단되면 예외를 발생시킵니다.
부울 tryLock(오랜 시간, TimeUnit 단위)이 InterruptedException을 발생시킵니다.
무효 잠금 해제();
//이 잠금에 바인딩된 조건을 반환합니다.
조건 newCondition();
}
잠금 사용
다음과 같이 코드 코드를 복사합니다.
잠금 잠금 = new ReentrantLock();
lock.lock();
노력하다{
//객체 상태 업데이트
}마지막으로{
//여기서 잠금을 해제하려면 최종 코드 블록이 있어야 합니다.
//그렇지 않으면 교착 상태 및 기타 활동 문제가 발생하기 쉽습니다.
lock.unlock();
}
재진입 잠금 기능
폴링 잠금 및 시간 제한 잠금
폴링 가능하고 시간 지정 가능한 잠금 요청은 무조건 잠금 획득과 다른 tryLock() 메서드를 통해 구현됩니다. ReentrantLock은 유연한 내결함성 메커니즘을 가질 수 있으며 교착 상태는 순차적 잠금으로 인해 발생하며 다른 스레드가 획득을 시도합니다. 잠글 때 차단되고 이미 보유하고 있는 잠금을 해제하지 않아 결국 교착 상태가 발생합니다. tryLock() 메서드가 잠금을 얻으려고 할 때 이미 다른 스레드가 잠금을 보유하고 있는 경우 차단 및 대기 대신 설정 메서드에 따라 즉시 반환됩니다. 동시에 보유하고 있던 잠금을 해제합니다. 반환된 내용에 따라 반환할 수 있습니다. 결과적으로 교착상태를 피하기 위해 재시도 또는 취소가 수행됩니다.
공평
ReentrantLock 생성자는 공정한 잠금과 불공정한 잠금(기본값)이라는 두 가지 옵션을 제공합니다. 소위 공정한 잠금이라고 하는 스레드는 요청을 발행한 순서대로 잠금을 획득하며 대기열 점프는 허용되지 않지만 불공정 잠금의 경우 대기열 점프가 허용됩니다. 스레드가 잠금 획득을 요청하면 잠금이 사용 가능한 경우입니다. , 그러면 이 스레드는 대기열에서 대기 중인 스레드를 건너뛰고 잠금을 획득합니다. 우리는 일반적으로 모든 잠금이 불공평하기를 원합니다. 잠금 작업을 수행할 때 공정성은 스레드 정지 및 스레드 복구의 오버헤드로 인해 성능을 크게 저하시키기 때문입니다. 상황을 생각해 보십시오. 스레드 A가 잠금을 보유하고 스레드 B가 잠금을 요청하므로 스레드 B가 일시중단됩니다. 스레드 A가 잠금을 해제하면 스레드 B가 활성화되어 동시에 잠금을 다시 획득하려고 시도합니다. C 또한 이 잠금을 획득하도록 요청하면 C 스레드는 B 스레드가 완전히 활성화되기 전에 이 잠금을 획득, 사용 및 해제할 가능성이 높습니다. 이는 B가 잠금을 획득하는 순간(B가 깨어난 후에만 잠금을 획득할 수 있음)이 지연되지 않고 처리량도 향상됩니다. 대부분의 경우 불공정 잠금의 성능은 공정 잠금의 성능보다 높습니다.
잠금 획득 작업이 중단될 수 있습니다.
lockInterruptible 메소드는 인터럽트에 대한 응답을 유지하면서 잠금을 획득하므로 다른 유형의 중단 불가능한 차단 작업을 만들 필요가 없습니다.
읽기쓰기잠금읽기쓰기잠금
ReentrantLock은 한 번에 하나의 스레드만 잠금을 보유할 수 있는 표준 뮤텍스 잠금입니다. 읽기-쓰기 잠금은 두 개의 Lock 개체를 노출하는데, 그 중 하나는 읽기 작업에 사용되고 다른 하나는 쓰기 작업에 사용됩니다.
다음과 같이 코드 코드를 복사합니다.
공용 인터페이스 ReadWriteLock {
/**
* 읽기에 사용된 잠금을 반환합니다.
*
* @return 읽기에 사용된 잠금을 반환합니다.
*/
잠금 readLock();
/**
* 쓰기에 사용된 잠금을 반환합니다.
*
* @return 쓰기에 사용된 잠금을 반환합니다.
*/
잠금 writeLock();
}
선택적 구현:
1. 출시 우선순위
2. 스레드 점프를 라인에서 읽습니다.
3. 재진입
4.다운그레이드
5.업그레이드
ReentrantReadWriteLock은 ReadWriteLock 인터페이스를 구현하고 생성자는 공정한 잠금과 불공정한 잠금이라는 두 가지 생성 방법을 제공합니다. 읽기-쓰기 잠금은 읽기는 많고 쓰기는 적은 상황에 적합하며 더 나은 동시성을 달성할 수 있습니다.
샘플 복사 코드는 다음과 같습니다.
공개 클래스 ReadWriteMap<K, V> {
비공개 맵<K, V> 맵;
개인 최종 ReadWriteLock 잠금 = 새로운 ReentrantReadWriteLock();
개인 최종 잠금 readLock = lock.readLock();
개인 최종 잠금 writeLock = lock.writeLock();
공개 ReadWriteMap(Map<K, V> 맵) {
this.map = 지도;
}
공개 V get(K 키) {
readLock.lock();
노력하다 {
return map.get(키);
} 마지막으로 {
readLock.unlock();
}
}
public void put(K 키, V 값) {
writeLock.lock();
노력하다 {
map.put(키, 값);
} 마지막으로 {
writeLock.unlock();
}
}
}