반응형

`java.util.concurrent.locks.AbstractOwnableSynchronizer`는 자바에서 멀티스레딩을 구현하는 데 사용되는 클래스 중 하나로, `Lock` 인터페이스를 구현하기 위해 추상 클래스로 정의되어 있습니다. 이 클래스는 동기화 매커니즘을 구현하고, 스레드의 소유권을 추적하는 데 사용됩니다.

이 클래스는 `Lock` 인터페이스를 구현하기 위해 `ReentrantLock`과 `ReentrantReadWriteLock` 등과 함께 사용됩니다. 이 클래스는 `Lock` 인터페이스의 메서드 중 `lock()`과 `unlock()`을 구현하고 있습니다. 또한 `AbstractQueuedSynchronizer`를 상속하고 있으므로 이 클래스의 인스턴스는 `ReentrantLock`과 `ReentrantReadWriteLock`과 같은 잠금 기능을 가진 동기화 클래스에 사용됩니다.

이 클래스의 주요 특징 중 하나는 `ExclusiveOwnerThread` 필드를 포함하는 것입니다. 이 필드는 현재 락을 소유하고 있는 스레드를 추적하기 위해 사용됩니다. `AbstractOwnableSynchronizer`를 상속한 클래스에서는 이 필드를 사용하여 현재 락을 소유하고 있는 스레드를 식별하고, 락을 재진입하려는 스레드가 이미 락을 소유하고 있는지 여부를 확인할 수 있습니다.

`AbstractOwnableSynchronizer`의 하위 클래스에서는 `setExclusiveOwnerThread(Thread)`과 `getExclusiveOwnerThread()` 메서드를 사용하여 `ExclusiveOwnerThread` 필드를 설정하고 반환할 수 있습니다. 이 필드는 락의 소유자가 변경될 때마다 갱신됩니다.

또한 `AbstractOwnableSynchronizer`는 다중 스레드 환경에서 안전한 동시성 제어를 위해 사용되는 여러 동기화 메커니즘에 대한 추상 메서드를 제공합니다. 이러한 메서드 중 하나인 `tryAcquire(int arg)`는 락을 얻으려는 스레드가 호출하며, `tryRelease(int arg)`는 락을 해제하려는 스레드가 호출합니다. 이러한 메서드는 구현된 구체적인 동기화 클래스에서 재정의되어 사용됩니다.

이 클래스는 락의 소유자를 추적하는 데 사용되는 기본적인 메커니즘을 제공하기 때문에 동기화 클래스를 구현할 때 편리하게 사용할 수 있습니다. 그러나 실제로 이 클래스를 직접 사용하는 것은 드문 일입니다. 대신, `ReentrantLock` 및 `ReentrantReadWriteLock`과 같은 클래스를 사용하여 락을 관리합니다.`AbstractOwnableSynchronizer`의 구현 예시를 살펴보면, 다음과 같은 코드가 있습니다.

 

public abstract class AbstractOwnableSynchronizer
    implements java.io.Serializable {

    private static final long serialVersionUID = 3737899427754241961L;

    protected AbstractOwnableSynchronizer() { }

    private transient Thread exclusiveOwnerThread;

    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }

    protected final Thread getExclusiveOwnerThread() {
        return exclusiveOwnerThread;
    }
}


위의 코드에서 `AbstractOwnableSynchronizer`는 추상 클래스로 정의되어 있습니다. `setExclusiveOwnerThread`와 `getExclusiveOwnerThread`는 락을 소유한 스레드를 추적하기 위한 메서드입니다. 이 메서드들은 `protected`로 정의되어 있기 때문에 하위 클래스에서만 사용될 수 있습니다. 또한 `exclusiveOwnerThread` 필드는 `transient`로 선언되어 있으므로 직렬화될 수 없습니다.

`AbstractOwnableSynchronizer`의 하위 클래스 중 하나인 `ReentrantLock`은 `AbstractOwnableSynchronizer`를 상속받아 락의 소유자를 추적하고, 재진입을 허용하는 락을 구현합니다. 이 클래스를 사용하여 다음과 같은 코드를 작성할 수 있습니다.

 

import java.util.concurrent.locks.ReentrantLock;

public class Example {

    private final ReentrantLock lock = new ReentrantLock();

    public void doSomething() {
        lock.lock();
        try {
            // 락을 얻은 후 수행할 작업
        } finally {
            lock.unlock();
        }
    }
}


위의 코드에서 `ReentrantLock` 클래스를 사용하여 락을 생성하고, `lock()` 메서드를 호출하여 락을 얻은 후 작업을 수행합니다. 작업이 완료되면 `unlock()` 메서드를 호출하여 락을 해제합니다.

`AbstractOwnableSynchronizer`는 멀티스레드 환경에서 안전한 동기화를 구현하기 위한 다양한 메커니즘을 제공합니다. 이 클래스를 상속하여 락을 구현할 때, 락의 소유자를 추적하는 기능을 구현할 수 있습니다. 하지만 실제로 `AbstractOwnableSynchronizer`를 사용하여 락을 구현하는 것보다 `ReentrantLock`과 같은 클래스를 사용하는 것이 더 편리합니다.`AbstractOwnableSynchronizer` 클래스는 보통 `ReentrantLock`과 같은 동기화 기본 요소를 구현할 때 사용됩니다. 아래는 `AbstractOwnableSynchronizer` 클래스를 이용해 `ReentrantLock`과 유사한 락을 구현하는 예제 코드입니다.

 

import java.util.concurrent.locks.AbstractOwnableSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.atomic.AtomicReference;

public class SimpleLock extends AbstractOwnableSynchronizer implements Lock {
    private static final long serialVersionUID = 7398518128377890585L;
    private static final int FREE = 0;
    private static final int BUSY = 1;

    private final AtomicReference<Thread> owner = new AtomicReference<>();
    private final AtomicReference<Thread> waitQueue = new AtomicReference<>();
    private final AtomicReference<Integer> state = new AtomicReference<>(FREE);

    @Override
    public void lock() {
        if (!tryLock()) {
            Thread current = Thread.currentThread();
            AtomicReference<Thread> waitQueueTail = new AtomicReference<>();
            waitQueue.set(waitQueueTail);
            while (!tryAcquire(current)) {
                LockSupport.park(this);
            }
            waitQueueTail.set(null);
        }
    }

    @Override
    public boolean tryLock() {
        Thread current = Thread.currentThread();
        if (state.compareAndSet(FREE, BUSY)) {
            owner.set(current);
            return true;
        } else if (owner.get() == current) {
            state.incrementAndGet();
            return true;
        }
        return false;
    }

    @Override
    public void unlock() {
        Thread current = Thread.currentThread();
        if (owner.compareAndSet(current, null)) {
            int newState = state.decrementAndGet();
            if (newState == FREE) {
                Thread next = waitQueue.getAndSet(null);
                if (next != null) {
                    LockSupport.unpark(next);
                }
            }
        }
    }

    @Override
    public Condition newCondition() {
        return new SimpleCondition(this);
    }

    private boolean tryAcquire(Thread current) {
        if (state.compareAndSet(FREE, BUSY)) {
            owner.set(current);
            return true;
        } else if (owner.get() == current) {
            state.incrementAndGet();
            return true;
        }
        return false;
    }

    private static class SimpleCondition implements Condition {
        private final SimpleLock lock;

        SimpleCondition(SimpleLock lock) {
            this.lock = lock;
        }

        @Override
        public void await() throws InterruptedException {
            throw new UnsupportedOperationException();
        }

        @Override
        public void awaitUninterruptibly() {
            throw new UnsupportedOperationException();
        }

        @Override
        public long awaitNanos(long nanosTimeout) throws InterruptedException {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean await(long time, TimeUnit unit) throws InterruptedException {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean awaitUntil(Date deadline) throws InterruptedException {
            throw new UnsupportedOperationException();
        }

        @Override
        public void signal() {
            lock.unlock();
        }

        @Override
        public void signalAll() {
            lock.unlock();
        }
    }
}


위의 코드에서는 `AbstractOwnableSynchronizer` 클래스를 상속하며, `Lock` 인터페이스를 구현하는 `SimpleLock` 클래스를 정의합니다.

 

 

반응형

+ Recent posts