使用aqs简单实现可重入锁

介绍

  • Lock接口, 该接口定义了java语言中显式锁的基本方法

在这里插入图片描述

  • AbstractQueuedSynchronizer抽象类, 采用模版方法设计模式, 其中的模版方法实现了锁的完整流程, 而我们只需要把需要重写的方法进行一个实现即可实现自己的锁.

    1. protected boolean tryAcquire(int arg) – 尝试获取许可
    2. protected boolean tryRelease(int arg) – 尝试释放许可
    3. protected boolean isHeldExclusively() – 当前锁是否被占用
  • 上代码

public class MyLock implements Lock {


	private static class Sync extends AbstractQueuedSynchronizer {

		@Override
		protected boolean tryAcquire(int arg) {

			int state = getState();

			// 如果state状态为0 标识无锁, 反之有锁

			// 第一次加锁
			if (compareAndSetState(0,1)){
				setExclusiveOwnerThread(Thread.currentThread());
				return true;
			}
			// 如果当前线程与占用锁的线程一致,表明线程重入
			if (Thread.currentThread() == getExclusiveOwnerThread()){
				compareAndSetState(state,state+1);
				return true;
			}

			// 返回false, 该线程将会加入到同步队列进行等待
			return false;
		}

		@Override
		protected boolean tryRelease(int arg) {

			// 这个方法只有拿到线程的锁会进入, 也就是只有一个线程会进入此方法
			int state = getState();
			// 进行减一操作
			setState(state-1);

			// 如果为0 , 表明已经完全释放, 把当前占用线程设置为空
			if (getState() == 0){
				setExclusiveOwnerThread(null);
			}

			return true;
		}

		/**
		 * 判断是否被占用
		 * */
		@Override
		protected boolean isHeldExclusively() {
			return getState()> 0;
		}
	}

	private 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 tryLock();
	}

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

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

  • 简单的可重入锁就已经完成, 关键在于加锁的时候对自身进行判断.

突发感想

代码始终不是重点, 算法,数据结构,才是真的核心, 而我们java程序员离核心总是那么远

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页