Java 并发工具类 Semaphore 线程信号量 AQS共享锁

一、Semaphore 简介

    Semaphore 是一个计数的信号量,维护了一定数量的许可,没有获取到许可的线程将会等待。内部持有了两个AQS的子类,分别是公平锁和非公平锁,二者主要的区别在于公平锁的获取会判断是否存在等待获取锁的线程,若有会直接放弃锁的争夺。Semaphore可以用来控制某个方法的并发数量,增加边界等。
    关于AQS同步器,可以看另一篇博客 AQS详解

二、Semaphore源码分析

    Semaphore内部用AQS的state表示许可的个数,当state等于0时,线程获取共享锁失败,state大于0时,线程获取到许可(共享锁),并将state减1,归还时将state加1。

    非公平锁获取锁,剩余许可小于0时,共享锁获取失败进入AQS的队列;
剩余许可大于0时,CAS将许可减1(acquires 为1)。

 final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }

    公平锁获取锁之前要判断有没有等待的线程:hasQueuedPredecessors(),如果有直接返回-1:获取锁失败。

 protected int tryAcquireShared(int acquires) {
            for (;;) {
                if (hasQueuedPredecessors())
                    return -1;
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
三、Semaphore实战

1.指定大小的池子 pool,代码来自Semaphore类注释。

 class Pool {
    private static final int MAX_AVAILABLE = 100;
    private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
 
    public Object getItem() throws InterruptedException {
      available.acquire();
      return getNextAvailableItem();
    }
 
    public void putItem(Object x) {
      if (markAsUnused(x))
        available.release();
    }
 
    // Not a particularly efficient data structure; just for demo
 
    protected Object[] items = ... whatever kinds of items being managed
    protected boolean[] used = new boolean[MAX_AVAILABLE];
 
    protected synchronized Object getNextAvailableItem() {
      for (int i = 0; i < MAX_AVAILABLE; ++i) {
        if (!used[i]) {
           used[i] = true;
           return items[i];
        }
      }
      return null; // not reached
    }
 
    protected synchronized boolean markAsUnused(Object item) {
      for (int i = 0; i < MAX_AVAILABLE; ++i) {
        if (item == items[i]) {
           if (used[i]) {
             used[i] = false;
             return true;
           } else
             return false;
        }
      }
      return false;
    }
  }}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值