Java并发之Semaphore
来源:互联网 发布:知乎二战德国石油 编辑:程序博客网 时间:2024/06/05 17:30
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。
一、方法摘要
- Semaphore(int permits):构造方法,创建具有给定的许可数和非公平锁的Semaphore。
- Semaphore(int permits, Boolean fair):构造方法,创建具有给定许可数和给定公平设置的Semaphore。
- void acquire():从此信号量获取一个许可,在提供一个许可前将阻塞,否则线程被中断。
- void acquire(int permits):从此信号量获取给定数目的许可,在提供这些许可前阻塞,或者线程已被中断。
- void acquireUninterruptibly():获取许可,无视中断。
- Boolean tryAcquire():仅在调用此信号量时存在一个许可,才从信号量获取许可。
- void release():释放一个许可,将其返回给信号量。
二、使用方法
Semaphore是一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire(),然后再获取许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。例如,下面的类使用信号量控制对内容池的访问:
public class SemaphoreTest {private static final int THREAD_COUNT = 30;private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);private static Semaphore s = new Semaphore(10);public static void main(String[] args) {for (int i = 0; i < THREAD_COUNT; i++) {threadPool.execute(new Runnable() {@Overridepublic void run() {try {s.acquire();//获取许可System.out.println("save data");s.release();//释放许可} catch (InterruptedException e) {}}});}threadPool.shutdown();}}
在代码中,虽然有30个线程在执行,但是只允许10个并发的执行。Semaphore的构造方法Semaphore(int permits) 接受一个整型的数字,表示可用的许可证数量。Semaphore(10)表示允许10个线程获取许可证,也就是最大并发数是10。Semaphore的用法也很简单,首先线程使用Semaphore的acquire()获取一个许可证,使用完之后调用release()归还许可证。还可以用tryAcquire()方法尝试获取许可证。
三、实现原理
结构类图
信号量内含了两个队列同步器,分别是公平的和非公平的。通过队列同步器来控制线程同步。
构造函数
public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairSync(permits); }
Semaphore内置了两个队列同步器,分别为公平的和非公平的。根据构造参数的不同,决定实现哪一个同步器。
acquire 方法
acquire()方法用来获取许可,这里的许可其实关联到队列同步器AQS的状态state。源码如下:
public void acquire() throws InterruptedException { sync.acquireSharedInterruptibly(1);//获取共享锁 }
AQS中,该方法的实现为:
public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0)//尝试获取同步 doAcquireSharedInterruptibly(arg);//尝试失败 则 继续等待 }
该方法为模板方法,需要对tryAcquireShared方法进行重写。对于非公平锁,源码如下:
protected int tryAcquireShared(int acquires) { return nonfairTryAcquireShared(acquires);//调用了父类方法 }
final int nonfairTryAcquireShared(int acquires) { for (;;) { int available = getState();//获取状态 int remaining = available - acquires;//更新状态 if (remaining < 0 || compareAndSetState(available, remaining)) return remaining;//返回新的状态值 } }
对于公平锁,则需要加上判断,该线程是否为同步队列的头结点才可。acquire本质上是交出同步器的state给线程。当state消耗完时(<=0)就无法再获得共享锁。
release 方法
release方法用来归还信号量。源码如下:
public void release() { sync.releaseShared(1);//调用同步器的释放共享锁 }
该方法调用了同步器的模板方法:
public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) {//尝试释放锁 doReleaseShared(); return true; } return false; }在Semaphore中,重写了tryReleaseShared方法:
protected final boolean tryReleaseShared(int releases) { for (;;) { int current = getState();//获取state值 int next = current + releases;//归还信号量 if (next < current) // overflow throw new Error("Maximum permit count exceeded"); if (compareAndSetState(current, next))//更新state return true; } }
阅读全文
0 0
- Java并发之Semaphore
- Java并发之Semaphore
- java并发编程之Semaphore
- java并发之Semaphore(信号量)
- Java并发之Semaphore详解
- java并发编程之Semaphore
- java 并发包之Semaphore
- Java并发之Semaphore详解
- Java并发之CountDownLatch、CyclicBarrier、Semaphore
- java并发之Semaphore(计数信号量)
- Java并发之CountDownLatch、CyclicBarrier和Semaphore
- Java 并发之 CountDownLatch、CyclicBarrier 和 Semaphore
- Java 并发之 CountDownLatch、CyclicBarrier 和 Semaphore
- Java 并发之 CountDownLatch、CyclicBarrier 和 Semaphore
- Java并发之Semaphore的源码分析
- java并发控制之Semaphore详解
- Java并发之CountDownLatch、CyclicBarrier和Semaphore
- Java并发之CountDownLatch、CyclicBarrier和Semaphore
- x264源代码简单分析:宏块分析(Analysis)部分-帧内宏块(Intra)
- AI发展受影响的高危岗位
- python + webdriver
- 器——Eclipse开发JAVA中如何Debug
- datasnap回调演示
- Java并发之Semaphore
- 1094. The Largest Generation (25)
- Softmax 函数的特点和作用
- uva12563 劲歌金曲
- 嵌套循环
- hihoCoder 1407 后缀数组二·重复旋律2 && POJ 1743 Musical Theme(最长不可重叠重复子串问题)
- 百练_2676:整数的个数
- 注解是什么,为什么要使用注解?
- Codeforces Round #382 (Div. 1) 736B Taxes