TwinsLock——自定义同步组件

TwinsLock——自定义同步组件


参考书籍:《Java并发编程的艺术》

设计目的

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

设计方案

  首先,确定访问模式。分为独占式访问和共享式访问,由于TwinsLock需要同一时刻至多两个线程能访问,因此属于共享式访问。因此需要使用同步器提供的acquireShared(int args)方法和Shared相关的方法,这就要求重写AQS的tryAcquireShared(int args)方法和tryReleaseShared(int args)方法,这样才能保证同步器的共享式同步状态的获取与释放方法得以执行。
  其次,定义资源数。TwinsLock同一时刻最多允许两个线程的同时访问,表名同步资源数为2,这样可以设置status为2,当一个线程获取成功,status减一,一个线程释放同步状态,status加一,且status合法取值为0、1、2。在同步状态变更时,需要使用compareAndSet(int except, int update)方法做原子性保证。
  最后,定义自定义同步器。自定义同步组件通过组合自定义同步器来完成同步功能,一般情况下自定义同步器会被定义为自定义同步组件的内部类。

代码实现

  运行下面的测试类,可以看看到线程名称成对输出,也就是在同一时刻只有两个线程能够获取到锁,这表明TwinsLock可以按照预期正常工作。可能有同学发现只有线程0和线程1抢到锁,这主要是因为持有锁的线程释放锁后,立即又进入循环并获取到锁,其他线程还来不及获取,要想看到其他线程获取到锁可以在释放锁后面sleep一小段时间。而且应该是非公平锁。
TwinsLock类

public class TwinsLock implements Lock {
    private final Sync sync = new Sync(2);
    private static final class Sync extends AbstractQueuedSynchronizer{
        Sync(int count){
            if(count <= 0){
                throw new IllegalArgumentException("count must large than zero.");
            }
            setState(count);
        }
        @Override
        protected int tryAcquireShared(int reducuCount) {
            for(;;){
                int current = getState();
                int newCount = current - reducuCount;
                if(newCount < 0 || compareAndSetState(current,newCount)){
                    return newCount;
                }
            }
        }
        @Override
        protected boolean tryReleaseShared(int returnCount) {
            for(;;){
                int current = getState();
                int newCount = current + returnCount;
                if(compareAndSetState(current,newCount)){
                    return true;
                }
            }
        }
    }
    public void lock(){
        sync.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;
    }

    public void unlock(){
        sync.releaseShared(1);
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

测试类

public class TwinsLockTest {
    @Test
    public void test() {
        final Lock lock = new TwinsLock();
        class Worker extends Thread {

            @Override
            public void run() {
                while (true) {
                    lock.lock();
                    try {
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName());
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
        for(int i = 0; i < 100; i++){
            Worker w = new Worker();
            w.setDaemon(true);
            w.start();
        }
        for(int i = 0; i < 10; i++){
            try {
                Thread.sleep(1000);
                System.out.println();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值