Java 병발-RENTrantLock
재 접속 가능 한 잠 금 ReentrantLock 은 JDK 1.5 에서 도입 되 었 으 며,기능 상 synchronized 키워드 와 유사 하지만,기능 상 synchronized 보다 강력 하 며,재 접속 가능 외 에 도 ReentrantLock 은 4 가지 특성 을 가지 고 있다.
、 、 、
synchronized 가 만족 하지 못 하 는 장면 에서 공정 한 잠 금,중단 허용,시간 초과 설정,여러 조건 변수 가 필요 한 경우 ReentrantLock 사용 을 고려 해 야 합 니 다.2.용법
ReenTrantLock 은 Lock 인 터 페 이 스 를 계 승 했 습 니 다.Lock 인 터 페 이 스 는 다음 과 같은 방법 이 있 습 니 다.
2.1 재 접속 가능
재 귀 자물쇠 라 고도 부 릅 니 다.같은 스 레 드 가 외부 방법 으로 자 물 쇠 를 가 져 올 때 이 스 레 드 에 들 어 가 는 내부 방법 은 자동 으로 자 물 쇠 를 가 져 옵 니 다.
void m1() {
lock.lock();
try {
// m2, ,
m2();
} finally {
lock.unlock()
}
}
void m2() {
lock.lock();
try {
// do something
} finally {
lock.unlock()
}
}
주:ReentrantLock 의
try-finally , finally
방법 이상 잠 금 이 풀 리 지 않도록 합 니 다.2.2 인 터 럽 트 자물쇠
。 , ,
。잠 금 의 lockInterruptibly 방법 을 호출 하면 잠 금 을 중단 할 수 있 습 니 다.이 방법 을 통 해 잠 금 을 가 져 올 때 다른 스 레 드 가 잠 금 을 가 져 오 기 를 기다 리 고 있다 면 이 스 레 드 는 중단 에 응답 할 수 있 습 니 다.즉,
.즉,두 스 레 드 가 동시에 lock.lockInterruptibly()를 통 해 특정한 자 물 쇠 를 가 져 오 려 고 할 때 만약 에 이때 스 레 드 A 가 자 물 쇠 를 가 져 왔 고 스 레 드 B 가 기다 리 기만 한다 면 스 레 드 B 에 threadB.interrupt()방법 으로 스 레 드 B 의 대기 과정 을 중단 할 수 있 습 니 다.예 는 다음 과 같다.public class ReentrantLockTest {
private static int account = 0;
private static ReentrantLock lock = new ReentrantLock();
public static void main (String [] args) {
Thread t1 = new Thread(()->{
try {
lock.lockInterruptibly();
System.out.println(" t1 :"+account++);
} catch (InterruptedException e) {
System.out.println(" t1 ");
}finally {
lock.unlock();
}
},"t1");
Thread t2 = new Thread(()->{
try {
lock.lockInterruptibly();
System.out.println(" t2 :"+account++);
// interrupt t1
t1.interrupt();
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(" t2 ");
}finally {
lock.unlock();
}
},"t2");
t2.start();
t1.start();
}
}
가능 한 실행 결 과 는:
주:위의 결 과 는 그 중의 한 가지 가능성 일 뿐 실제 운행 중 에 다른 결과 가 있 을 수 있 습 니 다.
일반적으로 중 단 된 사용 장면 은 다음 과 같은 몇 가지 가 있다.
2.3 공평 자물쇠
잠 금 가 져 오기 순 서 는 요청 한 절대 시간 순서,즉 FIFO 에 부합 되 며,먼저 도착 한 스 레 드 에서 잠 금 을 우선 가 져 옵 니 다.이미지 의 말 에 따 르 면 장삼,이사,왕 이 는 슈퍼마켓 에 가서 쇼핑 을 했 는데 계산대 가 하나 밖 에 없 었 다.3 명 이 모두 물건 을 샀 고 계산 을 하려 고 했다.공평 한 자 물 쇠 를 준비 했다.장삼 은 계산대 에 사람 이 없 는 것 을 발견 하고 바로 계산대 로 달 려 갔다.이사 와 왕 이 는 장삼 이 앞 에 있 는 것 을 보고 순 순 히 줄 을 서서 불공평 한 자 물 쇠 를 계산 했다.장삼 은 첫 번 째 로 계산대 에 가서 계산 을 했 고 이사 와 왕 이 는 네 번 째 로 계산 했다.그러나 이사(李 四)는 장삼(張 三)이 아직 끝나 지 않 은 것 을 발견 하고 장삼(張 三)뒤에 줄 을 섰 다.이때 왕 이도 왔 다.장삼(張 三)이 다 끝 난 것 을 발견 하 자 바로 앞 다 투어 계산 하 러 갔 고 이사(李 四)는 하늘 을 쳐 다 보 며"불공평 해"라 고 장탄 했다.
public class FairTest {
// true ReentrantLock ,false , false
private ReentrantLock lock = new ReentrantLock(true);
public void testFair() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() +" ");
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
FairTest fairLock = new FairTest();
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName()+" ");
fairLock.testFair();
};
Thread[] threadArray = new Thread[5];
for (int i=0; i<5; i++) {
threadArray[i] = new Thread(runnable);
threadArray[i].start();
}
}
}
가능 한 실행 결과:
이 를 통 해 알 수 있 듯 이 자물쇠 의 획득 순서 와 스 레 드 의 요청 자물쇠 의 순서 가 일치 합 니 다.
2.4 설정 시간 초과
try Lock()방법 은 자 물 쇠 를 한 번 가 져 오 려 고 시도 합 니 다.자 물 쇠 를 성공 적 으로 얻 은 후에 true 로 돌아 갑 니 다.그렇지 않 으 면 즉시 false 로 돌아 갑 니 다.그리고 스 레 드 는 즉시 다른 일 을 할 수 있 습 니 다.try Lock(long timeout,TimeUnit unit)은 시간 초과 매개 변 수 를 가 진 잠 금 을 신청 하 는 방법 입 니 다.차단 시간 은 주어진 값 을 초과 하지 않 습 니 다.주어진 시간 내 에 잠 금 을 성공 적 으로 가 져 오 면 true 로 돌아 갑 니 다.그렇지 않 으 면 시간 이 초 과 될 때 까지 막 힌 다음 flase 로 돌아 갑 니 다.
public class TimeoutTest{
private ReentrantLock lock = new ReentrantLock();
public void testTryLock() {
if (lock.tryLock()) {
try {
System.out.println(Thread.currentThread().getName() + " ");
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}else {
System.out.println(Thread.currentThread().getName() + " ");
}
}
public void testTryLockWithTimeout() {
try {
if (lock.tryLock(1, TimeUnit.SECONDS)){
try {
System.out.println(Thread.currentThread().getName() + " 1s ");
Thread.sleep(1000);
}finally {
lock.unlock();
}
}else {
System.out.println(Thread.currentThread().getName() + " 1s ");
}
}catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " was interrupted");
}
}
public static void main(String [] args) {
TimeoutTest timeouttest = new TimeoutTest();
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName()+" ");
timeouttest.testTryLock();
//timeouttest.testTryLockWithTimeout();
};
Thread[] threadArray = new Thread[5];
for (int i=0; i<5; i++) {
threadArray[i] = new Thread(runnable);
threadArray[i].start();
}
}
}
testTryLock()실행 가능 한 실행 결과:
testTry Lock WithTimeout()실행 가능 한 실행 결과:
2.5 여러 조건 을 귀속 가능
이것 은 synchronize 와 가장 중요 한 차이 점 입 니 다.synchronize 는 하나의 조건 에 해당 하고 ReentrantLock 은 여러 조건 을 연결 할 수 있 습 니 다.이것 은 여러 조건 변수 가 필요 한 장면 에서 ReentrantLock,예 를 들 어 대기 열 을 막 는 것 만 고려 할 수 있 습 니 다.대기 열 차단 요구:
, , ,
.아래 코드 는 JDK 1.8 에서 Array BlockingQueue 의 소스 코드 를 발췌 한 것 으로 간략 합 니 다.더 많은 것 을 알 고 싶 으 면 Array BlockingQueue 의 소스 코드 를 읽 거나 블 로그'차단 대기 열과 Array BlockingQueue 소스 코드 분석(JDK 1.8)'을 참고 하 십시오.public class ArrayBlockingQueue {
final Object[] items; //
int takeIndex; //
int putIndex; //
int count; //
final ReentrantLock lock; //
private final Condition notEmpty; //
private final Condition notFull; //
public ArrayBlockingQueue(int capacity) {
this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
//
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
//
private E dequeue() {
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
notFull.signal();
return x;
}
// ,
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
// while ,
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
// ,
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
// while ,
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
private static void checkNotNull(Object v) {
if (v == null)
throw new NullPointerException();
}
}
3.원리
원 리 는 블 로그 인 을 참고 하 십시오.이 블 로 그 는 매우 상세 하고 깊이 가 있 습 니 다.
4.총화
본 고 는 ReentrantLock 의 4 가지 특성
、 、 、
에 착안 하여 ReentrantLock 의 기본 적 인 용법 을 정리 하여 다음 에 ReentrantLock 의 원리 와 일상적인 개발 에서 ReentrantLock 을 능숙 하 게 사용 하 는 데 기반 을 다 져 주 었 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 Lock 및 Rlock 상세 정보sumOne ()과sumTwo () 함수는 두 개의 라인으로 분장하고sumOne () 함수에서 공유 자원 abce는 먼저 잠긴 다음에 1을 추가한 다음에 abce가 방출된다.sumTwo() 함수는 유사한 작업을 수행...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.