Java并发工具类之Semaphore
来源:互联网 发布:产品矩阵是什么意思 编辑:程序博客网 时间:2024/06/03 14:18
一、Semaphore的概念
Semaphore又叫信号量,用来控制同时访问特定资源的线程数量。它通过协调各个线程,以保证合理地使用公共资源。
Semaphore和CountDownLatch一样,也是维护了一个计数器,其本质是一个共享锁。
Semaphore有公平性和非公平性之分。
Semaphore的工作过程:
- 当一个线程想要访问某个共享资源时,它必须要先获取Semaphore;
- 当Semaphore > 0 时,获取该资源并使Semaphore – 1;
- 当Semaphore = 0,则表示全部的共享资源已经被其他线程全部占用,线程必须要等待其他线程释放资源;
- 当有线程释放资源时,Semaphore+1,其他线程可以争抢资源;
二、Semaphore的实现分析
前面分析可知,Semaphore的实现是共享锁。
构造函数
Semaphore有两个构造函数。
public Semaphore(int permits) { sync = new NonfairSync(permits); }public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairSync(permits);}
第一个构造函数中传入的是资源许可的数量,默认是非公平锁。
第二个构造函数传入资源许可的数量和一个boolean变量,该变量可实现公平锁。
Semaphore在使用时有两个主要方法,acquire()方法表示获取一个资源许可,而 release()方法表示释放一个资源许可。
资源获取:acquire()方法
调用acquire()方法获取一个资源:
public void acquire() throws InterruptedException { sync.acquireSharedInterruptibly(1); }
该方法调用AQS的acquireSharedInterruptibly()方法,以共享的模式获取同步状态:
public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); }
然后调用tryAcquireShared()方法,该方法由Sync的子类来实现:
- 如果是非公平模式,调用NonfairSync的tryAcquireShared()方法;
- 如果是公平模式,调用FairSync的tryAcquireShared()方法。
在前面的文章 ReentrantLock重入锁 中有提到公平与非公平的实现。
非公平模式
final int nonfairTryAcquireShared(int acquires) { for (;;) { int available = getState(); int remaining = available - acquires; if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; } }
remaining 表示剩余的资源许可,如果< 0,表示目前没有剩余的许可。当前线程继续等待。如果remaining >0 则执行CAS操作获取资源许可。
公平模式
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; } }
在公平模式的方法中,增加了一个判断,判断同步队列中是否有等待的线程:
- 有,则插入作为尾节点,线程阻塞;
- 没有,则参与资源竞争;
简而言之,公平模式就是要按等待队列中的顺序获取资源许可。
资源释放:release()方法
Semaphore调用release()方法释放资源许可,默认释放1个。
public void release() { sync.releaseShared(1); }
调用AQS的releaseShared()方法:
public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; }
调用Sync中重写的tryReleaseShared()方法(公平与非公平都是调用该方法),
protected final boolean tryReleaseShared(int releases) { for (;;) { int current = getState(); int next = current + releases; if (next < current) // overflow throw new Error("Maximum permit count exceeded"); if (compareAndSetState(current, next)) return true; } }
next代表如果许可释放成功,可用资源许可的数量。
这里可能有多个线程同时释放,因此利用CAS操作将资源许可数量置为next。
释放成功后,进入doReleaseShared()唤醒队列中等待的线程。
注:公平模式与非公平模式都是调用该release()方法。
- Java并发工具类之Semaphore
- java 并发工具类-Semaphore
- java并发之同步工具类二之信号灯semaphore
- Java并发之Semaphore
- Java并发之Semaphore
- 【死磕Java并发】-----J.U.C之并发工具类:Semaphore
- Java并发学习(十五)-并发工具Semaphore
- 并发工具类:信号量Semaphore
- java并发编程之Semaphore
- java并发之Semaphore(信号量)
- Java并发之Semaphore详解
- java并发编程之Semaphore
- java 并发包之Semaphore
- Java并发之Semaphore详解
- 多线程进阶之并发工具类第二篇:Semaphore、Exchanger
- Java线程(CountDownLatch、CyclicBarrier、Semaphore)并发控制工具类
- JAVA多线程系列--并发工具类(CountDownLatch, CyclicBarrier, Semaphore,Exchanger)
- Java并发编程-同步辅助类之Semaphore
- windows环境下python2和python3以及pip的共存
- Ubuntu云服务器tp框架遇到failed to open stream: Permission denied问题
- 1013. 数素数 (20)
- windows server 2012清除并重建SID(2016类似)
- 泛型算法
- Java并发工具类之Semaphore
- 百度图片下载器
- 接口实现模拟器
- python defacultdict
- 20171026-大胆,再大胆些
- servlet如何判断是哪个表单传来的数据???
- Centos配置ssh免密码互信登录
- Codeforces Round #442 (Div. 2)【solved : 6 / 6】
- selenium自动化(一)