用AQS自定义不可重入锁NoReentrantLock(附加一个消费者生产者模式应用案例)

本文内容参考自Java并发编程之美6.2.3章节。


基于AQS自定义的不可重入锁:

//用AQS自定义同步器——不可重入锁NoReentrantLock
public class NoReentrantLock implements Lock, java.io.Serializable {

    //内部类用于完成具体的工作
    private static class Sync extends AbstractQueuedSynchronizer {
        //锁是否被持有
        protected boolean isHeldExclusively(){
            return getState() == 1;
        }
        //如果锁没有被持有(state==0)则尝试获取锁
        public boolean tryAcquire(int acquires) {
            assert acquires == 1;
            if(compareAndSetState(0,1)){
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
        //尝试释放锁,设置state=0
        public boolean tryRelease(int releases) {
            assert releases == 1;
            if(getState()==0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        //提供条件变量的生成接口
        Condition newCondition() {
            return new ConditionObject();
        }
    }

    //创建一个Sync实例
    private final Sync sync = new Sync();

    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1,unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }

    public boolean isLocked() {
        return sync.isHeldExclusively();
    }
}


消费者生产者模式应用案例:
需要注意的是,两个条件变量notFull和notEmpty的调用不要搞混了(不小心写错出现死锁了,还以为是线程调用有问题,解决了半天。。。)

//生产者消费者模型测试AQS自定义的NoReentrantLock
public class PCTest {
    //创建不可重入锁和对应的两个条件变量
    final static NoReentrantLock lock = new NoReentrantLock();
    final static Condition notFull = lock.newCondition();
    final static Condition notEmpty = lock.newCondition();
    //定义一个并行的队列和队列的大小(仓库的大小)
    final static Queue<String> queue = new LinkedBlockingQueue<>();
    final static int queueSize = 10;
    private static int id = 0;

    private static class producerThread extends Thread {
        public void run(){
            lock.lock();    //获取独占锁
            try {

                //如果队列满则等待,这里循环条件判断避免虚假唤醒
                while(queue.size()==queueSize){
                    System.out.println("当前元素已满等待中...");
                    notEmpty.await();           //条件变量调用await使当前线程阻塞挂起
                }
                String ele = "ele" + String.valueOf(id++);
                System.out.println("生产出一个元素:"+ele);
                //生产一个元素到队列
                queue.add(ele);
                //队列中已经有元素可供消费了,所以用notFull来唤醒消费者线程
                notFull.signalAll();

            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();  //释放锁
            }
        }
    }

    private static class consumerThread extends Thread {
        public void run(){
            lock.lock();    //获取独占锁
            try {

                //如果队列为空则等待
                while(queue.size()==0) {
                    System.out.println("当前没有元素等待中...");
                    notFull.await();
                }

                //消费一个元素
                String ele = queue.poll();
                System.out.println("消费了一个元素: "+ele);
                //唤醒生产者线程
                notEmpty.signalAll();

            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();  //释放锁
            }
        }
    }

    public static void main(String[] args) {

        for(int i = 0 ; i < 50 ; i++) {
            producerThread producer = new producerThread();
            producer.start();
        }
        for(int i = 0 ; i < 50 ; i++) {
            consumerThread consumer = new consumerThread();
            consumer.start();
        }

    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值