자바 동시 프로그래밍 요약 9 : 세부 조건

자세한 내용 은 조건의 대기 및 신호 대기 / 알림 메커니즘에 대한 자세한 설명을 참조하십시오.

전체적으로 Object의 대기 및 알림 / 알림은 스레드 간의 대기 / 알림 메커니즘을 완료하기 위해 개체 모니터와 협력하는 것입니다.

그리고 Condition과 Lock이 협력하여 대기 알림 메커니즘을 완료합니다.

전자는 Java의 최하위 수준에 있고 후자는 제어 가능성과 확장 성이 더 높은 언어 수준 입니다.

두 가지를 사용하는 다른 방법 외에도 기능적 특성 에는 여전히 많은 차이 있습니다 .

  1. 조건은 비 응답 인터럽트를 지원할 수 있지만 객체 모드를 사용해서는 안됩니다.
  2. Condition은 여러 대기 대기열 (새 여러 Condition 객체)을 지원할 수 있지만 Object 모드는 하나만 지원할 수 있습니다.
  3. 조건은 제한 시간 설정을 지원할 수 있지만 Object는 지원하지 않습니다.

 

1. 조건 구현의 원리

1. 대기 대기열의 실현 원리 :

조건 개체 빌드가 전달 되고이 lock.newCondition(),메서드는 실제로 AQS의 내부 클래스 인 ConditionObject 개체를 만듭니다 .

잠금 메커니즘의 구현에서 AQS는 내부적으로 동기화 대기열을 유지합니다. 배타적 잠금 인 경우 잠금을 획득하지 못한 모든 스레드의 꼬리가 동기화 대기열에 삽입 됩니다 . 마찬가지로 조건은 내부적으로도 사용됩니다. 같은 방식으로, 하나는. 내부적으로 유지되는  대기 큐에 대한 의 condition.await 메소드를 호출하는 모든 스레드가 대기 큐에 추가되며, 스레드의 상태는로 변환되어 대기 상태입니다.

ConditionObject에는 firstWaiterlastWaiter의 두 가지 멤버 변수가 있습니다 .

/** First node of condition queue. */
private transient Node firstWaiter;
/** Last node of condition queue. */
private transient Node lastWaiter;

ConditionObject가 대기 큐의 헤드 및 테일 포인터를 보유하여 대기 큐를 관리하는 것을 볼 수 있습니다.

Node 클래스는 AQS에서 Node 클래스를 재사용하며 노드 상태 및 관련 속성은 AQS 구현에서 볼 수 있습니다.

Node 클래스에는 다음과 같은 속성이 있습니다.

// 후속 노드
노드 nextWaiter;

대기 대기열은 단방향 대기열 이며 이전에 AQS라고 말했을 때 동기화 대기열양방향 대기열 이라는 것을 알았습니다 .

  • condition.await 메서드를 호출 한 후 스레드는 그림과 같이 대기 큐에 차례로 삽입되며 큐의 스레드 참조는 Thread-0, Thread-1, Thread-2 ... Thread-8입니다.
  • 대기 대기열은 단방향 대기열입니다.

lock.newCondition () 메서드를 여러 번 호출하여 여러 조건 객체만들 수 있습니다 . 즉, 잠금 은 여러 대기 대기열을 보유 할 수 있습니다 .

Object를 사용하는 이전 방법은 실제로 Object Object 모니터에 하나의 동기화 대기열과 하나의 대기 대기열 만있을 수 있음을 의미합니다 .

동시 패키지의 잠금에는 동기화 대기열과 여러 대기 대기열이 있습니다.

2. 기다림의 원칙 :

현재 스레드가 condition.await () 메서드를 호출 한 후 현재 스레드는 잠금을 해제 한 다음 signal / signalAll이 될 때까지 대기 큐에 추가합니다. 그러면 현재 스레드가 대기 큐에서 동기화로 이동합니다. 잠금을 획득 할 때까지 큐 그런 다음 await 메서드에서 반환하거나 기다리는 동안 중단 될 때 중단됩니다 .

2.1 대기 대기열에 현재 스레드를 추가하는 방법은 무엇입니까?

현재 쓰레드에 의해 캡슐화 된 Node는 tail 삽입을 통해 wait queue에 삽입 할 수 있습니다 . 동시에 wait queue는 선행 노드가없는 chain queue 임을 알 수 있습니다 . AQS를 배우기 전에 우리는 동기화가 queue 는 선두 노드였습니다. Chain queue , 이것은 둘의 차이입니다.

2.2 잠금을 해제하는 과정?

AQS 템플릿 메서드 해제 메서드를 호출하여 AQS의 동기화 상태를 해제하고 동기화 대기열에서 헤드 노드의 후속 노드가 참조하는 스레드를 깨 웁니다 . 해제가 성공하면 정상적으로 반환되고 실패하면 예외가 발생합니다.

2.3 await 메소드를 종료하려면 어떻게해야합니까?

현재 스레드가 중단되거나 condition.signal / condition.signalAll 메서드가 호출됩니다. 현재 노드가 동기화 대기열로 이동 한 후  현재 스레드가 await 메서드를 종료하기위한 전제 조건입니다.

while 루프를 종료 한 후 acquireQueued(node, savedState)그는 AQS 기본 구현의 도입에 대해이 메서드를 호출 할 것입니다. 관심이 있다면 이 기사살펴볼 수 있습니다. 이 메서드의 역할은 동기화 상태를 얻기위한 지속적인 시도의 스레드 회전 프로세스에 있습니다. 성공할 때까지 (스레드가 잠금을 얻음) . 이것은 또한 await 메소드종료가 조건 참조 (association)를 획득 한 잠금이어야 함을 보여줍니다 .

3. 신호 및 signalAll의 실현 원리 :

signal 또는 signalAll 조건 메서드를 호출하면 대기 큐에서 대기 시간이 가장 긴 노드를 동기화 큐로 이동할 수 있으므로 노드가 잠금을 얻을 수 있습니다. 대기 큐는 선입 선출 (FIFO)에 따라 대기 큐의 헤드 노드는 대기 시간이 가장 긴 노드, 즉 조건의 신호 메서드가 호출 될 때마다 헤드 노드 여야합니다. 동기 큐로 이동됩니다.

조건 신호를 호출하기위한 전제 조건은 현재 스레드가 잠금을 획득 한 것입니다.이 메서드는 대기 대기열에있는 헤드 노드, 즉 대기 시간이 가장 긴 노드를 동기화 대기열로 이동하고 대기중인 스레드를 깨울 기회가 있기 전에 동기화 큐가 깨어났습니다. 즉, await 메서드의 LockSupport.park (this) 메서드에서 반환되어 await 메서드를 호출 한 스레드가 성공적으로 종료되도록 할 수 있습니다. .

signalAll과 signal 메서드의 차이점은 doSignalAll 메서드에 반영되어 있습니다. doSignal 메서드 는 대기중인 큐의 헤드 노드에서만 작동 한다는 것을 이미 알고 있습니다. 이 메서드는 대기중인 큐의 모든 노드가 동기화 큐로 이동한다는 사실 만 인식합니다 . 즉, 현재 condition.await () 메서드를 호출하는 각 스레드에 "알림"입니다.

4. 두 가지 생각을 결합 :

대기 알림 메커니즘 은 조건 에서 제공하는 await 및 signal / signalAll 메소드를 사용하여 구현할 수 있으며 ,이 메커니즘은 가장 고전적인 문제인 "생산자 및 소비자 문제"를 해결할 수 있습니다 .

이 사진은 매우 중요합니다. 이 그림을 이해하고 기억한다고 말할 수 있습니다!

 

추천

출처blog.csdn.net/ScorpC/article/details/113859719