MST

星途 面试题库

面试题:Java中如何基于AQS实现一个简单的非重入锁

请简述基于Java并发包中的AbstractQueuedSynchronizer(AQS)实现一个简单非重入锁的主要步骤,并给出关键代码片段示例。
41.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 主要步骤
    • 继承AQS:创建一个类继承自AbstractQueuedSynchronizer
    • 实现同步状态的获取与释放
      • 获取锁:重写tryAcquire方法,尝试获取同步状态。对于非重入锁,当同步状态为0时,表示锁未被占用,此时设置同步状态为1并返回true,表示获取锁成功;否则返回false
      • 释放锁:重写tryRelease方法,当同步状态为1时,将同步状态设为0并返回true,表示释放锁成功;否则返回false
    • 对外提供锁的操作方法:在自定义锁类中提供lockunlock方法,在lock方法中调用acquire(1),在unlock方法中调用release(1)
  2. 关键代码片段示例
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Lock;

public class SimpleNonReentrantLock implements Lock {
    // 内部同步器
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int acquires) {
            // 尝试获取锁,非重入
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int releases) {
            // 尝试释放锁
            if (getState() == 0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
    }

    private final Sync sync = new Sync();

    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    // 其他未实现的Lock接口方法
    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public Condition newCondition() {
        throw new UnsupportedOperationException();
    }
}