AQS(AbstractQueueSynchronizer),抽象队列同步器,是jdk提供的一种用来自定义实现同步组件的工具,java并发中的ReentrantLock/CountDownLatch/Semaphore也都是继承了它而实现。
现在陈达想要用它来实现一个自己的同步器,功能是限制同一时间内只有2个线程才能获取锁。
总的思路是同步组件QycLock实现Lock接口,实现加锁lock与解锁unlock。QycLock内部集成了一个继承自AQS的自定义同步器QycSync,主要的同步逻辑均在QynSync上,QycLcok仅是个包装。
QycSync继承自AQS,便是拥有了同步状态和同步队列,把初始状态值设为2,一个线程获取同步状态后,用CAS的方式让状态值-1,释放同步状态后,用CAS的方式让状态值+1。
QycSync代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| package com.iloveqyc.service.test.lock;
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock;
public class QycLock implements Lock {
private QycSync qycSync = new QycSync(2);
@Override public void lock() { qycSync.acquireShared(1); }
@Override public void lockInterruptibly() throws InterruptedException {
}
@Override public boolean tryLock() { return false; }
@Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return false; }
@Override public void unlock() { qycSync.releaseShared(1); }
@Override public Condition newCondition() { return null; }
static class QycSync extends AbstractQueuedSynchronizer {
QycSync(int count) { if (count <= 0) { throw new RuntimeException(); } setState(count); }
@Override protected int tryAcquireShared(int arg) { for (;;) { int currentState = getState(); int newState = currentState - 1; if (newState < 0) { System.out.println(Thread.currentThread().getName() + "到达时同步状态已经小于0,将会在同步队列中调用sun.misc.Unsafe.park,进入等待状态"); return newState; } boolean isSuccess = compareAndSetState(currentState, newState); if (!isSuccess) { System.out.println(Thread.currentThread().getName() + "尝试获取锁失败, 同步状态currentState预期为" + currentState + ", 实际不是"); continue; } return newState; } }
@Override protected boolean tryReleaseShared(int arg) { int currentState = getState(); int newState = currentState + 1; return compareAndSetState(currentState, newState); } } }
|
QycThread代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.iloveqyc.service.test.lock;
public class QycThread implements Runnable {
private QycLock qycLock;
public QycThread(QycLock qycLock) { this.qycLock = qycLock; }
@Override public void run() { qycLock.lock(); System.out.println(Thread.currentThread().getName() + "成功获取了锁!即将带着锁睡眠60s"); try { Thread.sleep(60000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "睡眠60s结束,即将释放锁"); qycLock.unlock(); }
}
|
main方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.iloveqyc.service.test.lock;
public class QycTest { public static void main(String[] args) { QycLock lock = new QycLock(); for (int i = 0; i < 10; i++) { Thread t = new Thread(new QycThread(lock)); t.setName(String.valueOf(i)); t.start(); } } }
|