AQS框架

转载:http://www.kejik.com/article/2486.html

AQS其实就是 java.util.concurrent.locks.AbstractQueuedSynchronizer 这个类。 阅读Java的并发包源码你会发现这个类是整个java.util.concurrent 的核心之一,也可以说是阅读整个并发包源码的一个突破口。

比如读 ReentrantLock 的源码你会发现其核心是它的一个内部类Sync :

整个包中很多类的结构都是如此,比如 Semaphore , CountDownLatch 都有一个内部类Sync ,而所有的Sync都是继承自 AbstractQueuedSynchronizer 。 所以说想要读懂Java并发包的代码,首先得读懂这个类。

AQS简核心是通过一个共享变量来同步状态,变量的状态由子类去维护,而AQS框架做的是:

  • 线程阻塞队列的维护
  • 线程阻塞和唤醒

共享变量的修改都是通过 Unsafe 类提供的CAS操作完成的。 AbstractQueuedSynchronizer 类的主要方法是acquirerelease ,典型的模板方法, 下面这4个方法由子类去实现:

protected boolean tryAcquire(int arg)
protected boolean tryRelease(int arg)
protected int tryAcquireShared(int arg)
protected boolean tryReleaseShared(int arg)

acquire方法用来获取锁,返回true说明线程获取成功继续执行,一旦返回false则线程加入到等待队列中,等待被唤醒,release方法用来释放锁。 一般来说实现的时候这两个方法被封装为lockunlock 方法。

下面的 SimpleLock 类实现了一个最简单非重入的互斥锁的功能,实际上它就是ThreadPoolExecutor$Worker 的实现(以后的文章会提到这个类)。

class SimpleLock extends AbstractQueuedSynchronizer {
	private static final long serialVersionUID = -7316320116933187634L;
	public SimpleLock() {
	}
	protected boolean tryAcquire(int unused) {
		if (compareAndSetState(0, 1)) {
			setExclusiveOwnerThread(Thread.currentThread());
			return true;
		}
		return false;
	}
	protected boolean tryRelease(int unused) {
		setExclusiveOwnerThread(null);
		setState(0);
		return true;
	}
	public void lock() {
		acquire(1);
	}
	public boolean tryLock() {
		return tryAcquire(1);
	}
	public void unlock() {
		release(1);
	}
	public boolean isLocked() {
		return isHeldExclusively();
	}
}
public static void main(String[] args) throws InterruptedException {
	final SimpleLock lock = new SimpleLock();
	lock.lock();
	for (int i = 0; i < 10; i++) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				lock.lock();
				System.out.println(Thread.currentThread().getId() + " acquired the lock!");
				lock.unlock();
			}
		}).start();
		// 简单的让线程按照for循环的顺序阻塞在lock上
		Thread.sleep(100);
	}
	System.out.println("main thread unlock!");
	lock.unlock();
}

运行上面的测试代码,结果如下:

main thread unlock!
9 acquired the lock!
10 acquired the lock!
11 acquired the lock!
12 acquired the lock!
13 acquired the lock!
14 acquired the lock!
15 acquired the lock!
16 acquired the lock!
17 acquired the lock!
18 acquired the lock!

会发现等待的线程是按照阻塞时的顺序依次获取到锁的。 这是因为AQS是基于一个叫 CLH lock queue 的一个变种来实现线程阻塞队列的,我们下一篇文章就来简单了解下CLH lock queue。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值