设计一个同步工具:该工具在同一时刻,只允许至多两个线程同时访问,超过两个线程的
    访问将被阻塞,我们将这个同步工具命名为TwinsLock。

    要求同步工具支持两个线程同时获得锁,所以需要acquireShared这个共享的方法。

    看一下AQS中acquireShared的实现

    1. public final void acquireShared(int arg) {
    2. // 调用tryAcquireShared方法
    3. if (tryAcquireShared(arg) < 0)
    4. // 当返回结果小于0的时候,进行阻塞
    5. doAcquireShared(arg);
    6. }
    7. // 没有实现,是留给子类实现的
    8. protected int tryAcquireShared(int arg) {
    9. throw new UnsupportedOperationException();
    10. }

    因此需要一个类实现tryAcquireShared方法。

    同理,releaseShared也是需要实现tryReleaseShared方法。

    1. public final boolean releaseShared(int arg) {
    2. if (tryReleaseShared(arg)) {
    3. doReleaseShared();
    4. return true;
    5. }
    6. return false;
    7. }
    8. protected boolean tryReleaseShared(int arg) {
    9. throw new UnsupportedOperationException();
    10. }

    实现:

    1. public class TwinsLock implements Lock {
    2. // 在Lock中需要一个同步器,有2个计数
    3. Sync sync = new Sync(2);
    4. // 同步器继承AQS
    5. private static final class Sync extends AbstractQueuedSynchronizer{
    6. Sync(int count) {
    7. if (count <= 0) {
    8. throw new IllegalArgumentException();
    9. }
    10. setState(count);
    11. }
    12. @Override
    13. protected int tryAcquireShared(int reduceCount) {
    14. for (;;){
    15. int cur = getState();
    16. // 获取加锁后state的值
    17. int newCount = cur - reduceCount;
    18. // 如果小于0,说明无法加锁,自旋
    19. // 如果cas失败,说明加锁失败,自旋
    20. if (newCount < 0 || compareAndSetState(cur, newCount)){
    21. return newCount;
    22. }
    23. }
    24. }
    25. @Override
    26. protected boolean tryReleaseShared(int returnCount) {
    27. for (;;) {
    28. int cur = getState();
    29. int newCount = cur + returnCount;
    30. if (compareAndSetState(cur, newCount)) {
    31. return true;
    32. }
    33. }
    34. }
    35. }
    36. @Override
    37. public void lock() {
    38. sync.acquireShared(1);
    39. }
    40. @Override
    41. public void lockInterruptibly() throws InterruptedException { }
    42. @Override
    43. public boolean tryLock() { return false; }
    44. @Override
    45. public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return false; }
    46. @Override
    47. public void unlock() {
    48. sync.releaseShared(1);
    49. }
    50. @Override
    51. public Condition newCondition() { return null; }
    52. }

    当前以上代码实际上是有点小问题的,因为释放锁的时候没有进行判断是否该线程已经上锁。
    这部分的释放锁可以去看ReentrantReadWriteLock中的实现。