1.介绍
AQS,AbstractQueuedSynchronizer,即队列同步器。它是构建锁或者其他同步组件的基础框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等),JUC并发包的作者(Doug Lea)期望它能够成为实现大部分同步需求的基础。它是JUC并发包中的核心基础组件。
2.state状态
AQS使用一个int类型的成员变量state来表示同步状态,当state>0时表示已经获取了锁,当state = 0时表示释放了锁。它提供了三个方法(getState()、setState(int newState)、compareAndSetState(int expect,int update))来对同步状态state进行操作,当然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) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
代码示例:
public void stateTest() {
int state = getState();
System.out.println("state:" + state);
setState(1);
state = getState();
System.out.println("state:" + state);
boolean bFlag = this.compareAndSetState(1, 2);
state = getState();
System.out.println("state:" + state);
}
输出结果
state:0
state:1
state:2
3.tryAcquire和tryRelease
2个方法需要重写,即对state状态维护的策略,如下示例代码,实现独占锁机制
public static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
@Override
protected final boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected final boolean tryRelease(int releases) {
if (getState() == 0) {
throw new IllegalMonitorStateException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
}
测试代码:
public void tryAcquireTest() {
boolean bFlag=tryAcquire(1);
if(bFlag)
{
try {
System.out.println("working");
TimeUnit.SECONDS.sleep(5);
System.out.println("worked");
} catch (InterruptedException e) {
e.printStackTrace();
}
tryRelease(1);
}
}
@Test
public void test2()
{
Sync sync=new Sync();
sync.tryAcquireTest();
}
4.acquire和release
tryAcquire如果在多线程环境情况下调用,只会在tryAcquire返回true时才执行,返回false则不执行代码,这不符合代码逻辑
测试代码:
@Test
public void test3() throws InterruptedException {
Sync sync=new Sync();
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
sync.tryAcquireTest();
}
});
Thread thread2=new Thread(new Runnable() {
@Override
public void run() {
sync.tryAcquireTest();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
结果输出:
working
worked
可以使用acquire和release方法来实现以上逻辑
public void acquireTest() {
acquire(1);
try {
System.out.println("working");
TimeUnit.SECONDS.sleep(2);
System.out.println("worked");
} catch (InterruptedException e) {
e.printStackTrace();
}
release(1);
}
输出结果:
working
worked
working
worked
5.FIFO队列
acquire实现了一个模板方法,当tryAcquire返回false,则将当前线程添加到一个队列中,这个点是理解的关键点
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
参考:
网友评论