Juc并发编程09——自己动手实现排他锁

本文介绍了如何基于AQS(AbstractQueuedSynchronizer)实现一个简单的非重入排他锁。通过创建内部类sync继承AQS并覆盖相关方法,如tryAcquire和tryRelease,实现了加锁和解锁的核心逻辑。在加锁过程中,使用CAS操作确保线程安全;解锁时,检查当前线程是否为锁的所有者,并释放锁状态。
摘要由CSDN通过智能技术生成

我们已经了解了AQS的的基本原理了,不如自己仿照其它锁实现一个排他锁吧。

要求如下:同一时间只允许一个线程持有锁,不要求可重入(反复加锁直接忽视即可)。

(1)实现Lock接口

public class Demo23 {
    public static void main(String[] args) {

    }

    private static class myLock implements Lock{

        @Override
        public void lock() {

        }

        @Override
        public void lockInterruptibly() throws InterruptedException {

        }

        @Override
        public boolean tryLock() {
            return false;
        }

        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return false;
        }

        @Override
        public void unlock() {

        }

        @Override
        public Condition newCondition() {
            return null;
        }
    }
}

(2) 创建内部类sync继承AQS,内部调用sync完成逻辑

public class Demo23 {
    public static void main(String[] args) {
			 myLock lock = new myLock();
        lock.lock();
    }

    private static class myLock implements Lock{

        private class sync extends AbstractQueuedSynchronizer {

            @Override
            protected boolean tryAcquire(int arg) {
                return super.tryAcquire(arg);
            }

            @Override
            protected boolean isHeldExclusively() {
                return getExclusiveOwnerThread() == Thread.currentThread();
            }

            protected  Condition newCondition() {
                return new ConditionObject();
            }

        }

        sync sync = new sync();

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

        @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 void unlock() {
            sync.release(1);
        }

        @Override
        public Condition newCondition() {
            return sync.newCondition();
        }
    }
}

上面代码的运行结果如下。

/home/wangzhou/IdeaProjects/jucdemo/src/com/wangzhou/Demo21.java:11:24
java: 未报告的异常错误java.lang.InterruptedException; 必须对其进行捕获或声明以便抛出

这是因为其父类的tryAcquire方法实现如下。

    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

(3)实现tryAcquire
先看看其它锁怎么做的。比如公平锁。

    protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

上面代码包含可重入逻辑,我们这里如果重入直接忽略,返回false,因此核心逻辑就只需要进行一个CAS操作了。

  @Override
            protected boolean tryAcquire(int acquires) {
                if(isHeldExclusively()) {
                    return true;
                }
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
                return false;
            }

加锁过程已经完成,您可以自行测试,接下来我们来实现解锁功能。

同样先看看其它锁怎么实现。

  protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

我们要实现的逻辑也很简单,没加锁的情况下不允许解锁。加锁的情况下解锁。

         @Override
            protected boolean tryRelease(int args) {
                if(getState() == 0) {
                    throw new UnsupportedOperationException();
                }
                if(isHeldExclusively()) {
                    setExclusiveOwnerThread(null);
                    setState(0);
                    return true;
                }
                return false;
            }

测试.

public static void main(String[] args) throws InterruptedException {
        myLock lock = new myLock();
        lock.lock();
        new Thread(() ->{
            lock.lock();
            System.out.println("thread2 get lock");
            lock.unlock();
        }).start();
        TimeUnit.SECONDS.sleep(1);
        lock.unlock();
        System.out.println("thread 1 unlock");
    }

在这里插入图片描述
condition请读者自测。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半旧518

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值