并发编程-使用AQS实现一个自己的可重入锁

之前发布过一个利用AQS实现一个简单的同步锁,但是不可以重入。

并发编程-利用AbstractQueuedSynchronizer(AQS)实现一个自己的锁

今天再实现一个可重入的同步锁。

package cn.bikan8;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @Author 小浩
 * @Date 2020/6/28 17:24
 * @Version 1.0
 * 利用AQS实现一个自己的可重入锁
 **/
public class MyReentrantLock implements Lock {
    private static class Syn extends AbstractQueuedSynchronizer {
        //       获取锁
        @Override
        protected boolean tryAcquire(int arg) {
//           如果当前state为0说明还没有线程获取到锁,直接尝试拿锁即可
            if (getState() == 0) {
                if (compareAndSetState(0, 1)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
//           如果state不是0 判断是不是当前线程重入 是的话直接加重入次数,
//           这里不用CAS是因为拿到锁的线程只有一个,不会有线程安全问题
            } else if (Thread.currentThread() == getExclusiveOwnerThread()) {
                setState(getState() + arg);
                return true;
            }

            return false;
        }

        //      释放锁
        @Override
        protected boolean tryRelease(int arg) {
            if (Thread.currentThread() != getExclusiveOwnerThread()) {
                try {
                    throw new Exception("错误");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
//          重入锁需要判断是否为0 为0才是真正的释放成功 >0则是减少一次重入次数
            int state = getState() - arg;
            setState(state);
            if (state == 0) {
                return true;
            } else {
                return false;
            }
        }

        //  Condition
        public Condition newCondition() {
            return new ConditionObject();
        }
    }

    private static Syn syn = new Syn();

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

    @Override
    public void lockInterruptibly() throws InterruptedException {
        syn.acquireInterruptibly(1);
    }

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

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

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

    @Override
    public Condition newCondition() {
        return syn.newCondition();
    }
}
package cn.bikan8;

import java.net.URLDecoder;

/**
 * @Author 小浩
 * @Date 2020/6/19 13:07
 * @Version 1.0
 **/
public class ReentrantLockTest {
    private MyReentrantLock myReentrantLock = new MyReentrantLock();

    public void getLock1() {
        myReentrantLock.lock();
        try {
            System.out.println("我第一次拿到了锁");
            getLock2();
        } finally {
            myReentrantLock.unlock();
        }
    }

    public void getLock2() {
        myReentrantLock.lock();
        try {
            System.out.println("我第二次拿到了锁");
        } finally {
            myReentrantLock.unlock();
        }
    }
    public static void main(String[] args) throws Exception {
          ReentrantLockTest reentrantLockTest = new ReentrantLockTest();
          reentrantLockTest.getLock1();
    }


}

 

测试发现我们自己写的锁可以重入,并且把锁放之前我们自己实现的不同步锁的测试类中,是线程的安全的。

© 版权声明
THE END
喜欢就支持以下吧
点赞0
分享
评论 抢沙发