잠금에서 조건의 역할

Condition 인터페이스는 Lock 인터페이스에서 제공하는 메커니즘으로, 스레드 간에 질서 있는 방식으로 통신하는 데 도움이 됩니다. 스레드가 특정 조건이 충족될 때까지 기다려야 하는 경우 Condition의 await 메서드를 호출하여 스레드를 대기 상태로 전환할 수 있습니다. 다른 스레드가 해당 조건을 충족하면 Condition의 signal 또는 signalAll 메서드를 호출하여 해당 스레드를 깨울 수 있습니다.

다음은 Condition을 사용하여 스레드 통신을 구현한 예입니다.

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyQueue<T> {
    
    
    private final Object[] items;
    private int head;
    private int tail;
    private int count;
    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    public MyQueue(int capacity) {
    
    
        items = new Object[capacity];
    }
    public void put(T item) throws InterruptedException {
    
    
        lock.lock();
        try {
    
    
            while (count == items.length) {
    
    
                notFull.await();
            }
            items[tail] = item;
            if (++tail == items.length) {
    
    
                tail = 0;
            }
            count++;
            notEmpty.signalAll();
        } finally {
    
    
            lock.unlock();
        }
    }
    public T take() throws InterruptedException {
    
    
        lock.lock();
        try {
    
    
            while (count == 0) {
    
    
                notEmpty.await();
            }
            Object item = items[head];
            if (++head == items.length) {
    
    
                head = 0;
            }
            count--;
            notFull.signalAll();
            return (T) item;
        } finally {
    
    
            lock.unlock();
        }
    }
}

위의 예에서는 ReentrantLock 및 Condition을 사용하여 스레드 간의 통신을 실현하는 간단한 대기열 클래스 MyQueue를 구현했습니다. 그 중 notFull과 notEmpty는 각각 대기열이 가득 차지 않은 상태와 비어 있지 않은 상태를 나타냅니다.

put 메소드에서 대기열이 가득 차면 스레드는 다른 스레드가 notEmpty.signalAll()을 호출할 때까지 대기 상태로 들어가기 위해 notFull.await()를 호출합니다. 잠금을 해제하기 전에 lock.unlock()을 사용해야 합니다.

take 메소드에서 큐가 비어있을 때 스레드는 다른 스레드가 notFull.signalAll()을 호출할 때까지 대기 상태로 들어가기 위해 notEmpty.await()를 호출합니다. 메서드가 반환되기 전에 lock.unlock()을 사용해야 합니다.

Condition을 사용하여 스레드 통신을 구현하려면 Lock의 보호 아래 수행해야 합니다. 시스템 호출 조건 변수는 경쟁 조건이 없도록 잠금을 획득해야 합니다.

참고:
스레드는 대기 조건이 충족되면 await 메서드를 호출하기 때문에 이 메서드는 스레드가 잠금을 해제하고 다른 스레드가 해당 signal 또는 signalAll 메서드를 호출하여 깨울 때까지 대기 상태에 들어가도록 합니다. 이 예에서 대기열이 가득 차면 스레드는 다른 스레드가 notEmpty.signalAll()을 호출하여 깨어날 때까지 기다리기 위해 notFull.await()를 호출합니다.
따라서 Condition을 사용하여 스레드 간 통신을 구현하는 경우 적절한 시간에 해당 메서드를 호출하여 스레드의 정확성을 보장하고 무한 루프가 발생하지 않도록 해야 합니다.

Supongo que te gusta

Origin blog.csdn.net/weixin_43031220/article/details/130655170
Recomendado
Clasificación