Java-java.util.concurrent.locks.AbstractQueuedSynchronizer

这个类简称AQS,如果我们要实现的功能是有获取和释放这两个操作,并且获取操作总是能够阻塞,那么我们就应该创建一个锁,并且这个锁继承AbstractQueuedSynchronizer,因为无论是获取,还是释放,都是依赖状态的操作

二:AQS中的state属性

private volatile int state;

protected final int getState() {
    
    
    return state;
}
protected final void setState(int newState) {
    
    
    state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
    
    
    return STATE.compareAndSet(this, expect, update);
}

使用state来管理状态的类非常多,例如
ReentranLock中的锁用该字段表示持有锁的线程已经持有了多少次(可重入)
Semaphore中的锁用该字段表示剩余的许可数量
FutureTask中的锁用该字段表示任务的状态(未开始,运行,完成,取消)

二:AQS中的exclusiveOwnerThread属性
exclusiveOwnerThread表示在同步互斥锁的功能中,当前持有锁的线程是哪个,exclusiveOwnerThread与state两个属性配合使用,可以实现任意独占锁功能

/**
 * 表示当前持有锁的线程
 */
private transient Thread exclusiveOwnerThread;

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

protected final Thread getExclusiveOwnerThread() {
    
    
    return exclusiveOwnerThread;
}

虽然concurrent包提供了能实现所有需求的类,但是本文出于学习其原理和其思想的目的,有必要说一下AQS最重要的编程范式,也就是说,你要使用AQS,那么就必须得按照这个代码模板去写,因为Doug Lee就是这样要求的,这也是模板设计思想,AQS中有下面四个常用的模板方法

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

当实现上锁解锁相关需求的时候,实现这个需求的类叫做A,那么类A中,应该有一个内部类,这个内部类就是锁,用来辅助类A来实现获取和释放操作,比如ReentranLock与它的内部类Sync之间的关系,下面例子实现了共享锁这样一个功能,最开始,任何线程都调用await,都无法执行下去,都会阻塞,当有任意一个线程调用signal的时候,之前调用await的那些线程都开始执行

public class MysShareLock {
    
    
	SharedSync sharedSync = new SharedSync();
	public void await() {
    
    
		sharedSync.acquireShared(0);
	}
	public void signal() {
    
    
		sharedSync.releaseShared(0);
	}
	// 这个内部类就是锁
	private class SharedSync extends AbstractQueuedSynchronizer {
    
    
		@Override
		protected boolean tryReleaseShared(int arg) {
    
    
			setState(1);
			return true;
		}
		// 大于0就能获取到锁,注意与等于0的区别,看注释
		@Override
		protected int tryAcquireShared(int arg) {
    
    
			if (getState() == 1) {
    
    
				return 1;
			}
			return -1;
		}
	}
	// 
	public static void main(String[] args) throws InterruptedException {
    
    
		MysShareLock tl = new MysShareLock();
		new Thread(() -> {
    
    
			System.out.println("T1调用await");
			tl.await();
			System.out.println("T1调用await完毕");
		}).start();
		new Thread(() -> {
    
    
			System.out.println("T2调用await");
			tl.await();
			System.out.println("T2调用await完毕");
		}).start();
		new Thread(() -> {
    
    
			System.out.println("T3调用await");
			tl.await();
			System.out.println("T3调用await完毕");
		}).start();
		Thread.sleep(3000);
		new Thread(() -> {
    
    
			System.out.println("T4要让T1,T2,T3都继续执行");
			tl.signal();
		}).start();
	}
}

下面的例子是一个互斥锁的实现

public class MysMutexLock {
    
    

	Sync sync = new Sync();

	public void luck() {
    
    
		sync.acquire(0);
	}

	public void unluck() {
    
    
		sync.release(0);
	}

	private class Sync extends AbstractQueuedSynchronizer {
    
    
		@Override
		protected boolean tryRelease(int arg) {
    
    
			setState(1);
			return true;
		}

		// true表示可以获取锁
		@Override
		protected boolean tryAcquire(int arg) {
    
    
			if (getState() == 1) {
    
    
				return true;
			}
			return false;
		}
	}

	public static void main(String[] args) throws InterruptedException {
    
    
		MysMutexLock tl = new MysMutexLock();
		new Thread(() -> {
    
    
			System.out.println("T1调用luck");
			tl.luck();
			System.out.println("T1调用luck完毕");
		}).start();
		new Thread(() -> {
    
    
			System.out.println("T2调用luck");
			tl.luck();
			System.out.println("T2调用luck完毕");
		}).start();
		new Thread(() -> {
    
    
			System.out.println("T3调用luck");
			tl.luck();
			System.out.println("T3调用luck完毕");
		}).start();
		Thread.sleep(3000);
		new Thread(() -> {
    
    
			System.out.println("T4释放锁,T1,T2,T3不一定谁能获取到锁");
			tl.unluck();
		}).start();
		while (true) {
    
    
		}
	}
}

猜你喜欢

转载自blog.csdn.net/u011624903/article/details/111042803