设计一个同步工具:该工具在同一时刻,只允许至多两个线程同时访问,超过两个线程的
访问将被阻塞,我们将这个同步工具命名为TwinsLock。
要求同步工具支持两个线程同时获得锁,所以需要acquireShared这个共享的方法。
看一下AQS中acquireShared的实现
public final void acquireShared(int arg) {// 调用tryAcquireShared方法if (tryAcquireShared(arg) < 0)// 当返回结果小于0的时候,进行阻塞doAcquireShared(arg);}// 没有实现,是留给子类实现的protected int tryAcquireShared(int arg) {throw new UnsupportedOperationException();}
因此需要一个类实现tryAcquireShared方法。
同理,releaseShared也是需要实现tryReleaseShared方法。
public final boolean releaseShared(int arg) {if (tryReleaseShared(arg)) {doReleaseShared();return true;}return false;}protected boolean tryReleaseShared(int arg) {throw new UnsupportedOperationException();}
实现:
public class TwinsLock implements Lock {// 在Lock中需要一个同步器,有2个计数Sync sync = new Sync(2);// 同步器继承AQSprivate static final class Sync extends AbstractQueuedSynchronizer{Sync(int count) {if (count <= 0) {throw new IllegalArgumentException();}setState(count);}@Overrideprotected int tryAcquireShared(int reduceCount) {for (;;){int cur = getState();// 获取加锁后state的值int newCount = cur - reduceCount;// 如果小于0,说明无法加锁,自旋// 如果cas失败,说明加锁失败,自旋if (newCount < 0 || compareAndSetState(cur, newCount)){return newCount;}}}@Overrideprotected boolean tryReleaseShared(int returnCount) {for (;;) {int cur = getState();int newCount = cur + returnCount;if (compareAndSetState(cur, newCount)) {return true;}}}}@Overridepublic void lock() {sync.acquireShared(1);}@Overridepublic void lockInterruptibly() throws InterruptedException { }@Overridepublic boolean tryLock() { return false; }@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return false; }@Overridepublic void unlock() {sync.releaseShared(1);}@Overridepublic Condition newCondition() { return null; }}
当前以上代码实际上是有点小问题的,因为释放锁的时候没有进行判断是否该线程已经上锁。
这部分的释放锁可以去看ReentrantReadWriteLock中的实现。
