加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java 7之多线程- Semaphore--转载

发布时间:2020-12-14 06:20:03 所属栏目:Java 来源:网络整理
导读:Semaphore用于保存当前可用许可的数量。是通过共享锁实现的。根据共享锁的获取原则,Semaphore分为"公平信号量"和"非公平信号量"。 "公平信号量"和"非公平信号量"的释放信号量的机制是一样的!不同的是它们获取信号量的机制:线程在尝试获取信号量许可时,对

Semaphore用于保存当前可用许可的数量。是通过共享锁实现的。根据共享锁的获取原则,Semaphore分为"公平信号量"和"非公平信号量"。

"公平信号量"和"非公平信号量"的释放信号量的机制是一样的!不同的是它们获取信号量的机制:线程在尝试获取信号量许可时,对于公平信号量而言,如果当前线程不在队列的头部,则排队等候;而对于非公平信号量而言,无论当前线程是不是在队列的头部,它都会直接获取信号量。该差异具体的体现在,它们的tryAcquireShared()函数的实现不同。

如果要使用Semaphore对象时,首先通过构造函数取得对象,如下:

Semaphore( permits) { sync = Semaphore( permits, fair) { sync = fair ? FairSync(permits) :

然后就可以调用Semaphore对象进行信号量的获取了,如下:

acquire() 1<span style="color: #0000ff;">public <span style="color: #0000ff;">void acquire(<span style="color: #0000ff;">int permits) <span style="color: #0000ff;">throws<span style="color: #000000;"> InterruptedException {
<span style="color: #0000ff;">if (permits < 0) <span style="color: #0000ff;">throw <span style="color: #0000ff;">new<span style="color: #000000;"> IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}

1、公平信号量的获取

首先来看公平信号量的获取,方法如下:

acquireSharedInterruptibly( arg) (tryAcquireShared(arg) < 0

如果tryAcquireShared()方法获取失败,通常会返回一个小于0的数量。Semaphore中公平锁对应的tryAcquireShared()实现如下:

tryAcquireShared( -1 available = getState(); remaining = available -=0”,则设置可以获得的信号量许可数为remaining。 (remaining < 0 ||

返回的是remaining,如果为-1,表示获取失败。如果为>=0,则预示了其他共享获取操作能否成功。

如上方法获取失败后,调用doAcquireSharedInterruptibly()方法,如下:

doAcquireSharedInterruptibly( arg) Node node = failed = Node p = (p == r = (r >= 0= ; failed = (shouldParkAfterFailedAcquire(p,node) &&

2、非公平信号量的获取

tryAcquireShared(

在这个方法里调用了如下方法:

nonfairTryAcquireShared( acquires) { available = remaining = available - (remaining < 0 || compareAndSetState(available,remaining))=0,则通过CAS方式更新当前许可的数量

判断当前剩余的信号量许可数,返回小于0的数表示获取失败,大于等于0表示成功。

非公平和公平主要体现在tryAcquireShared()方法的实现上。

(1)非公平获取 如果当前可用的信号量许可大于等于请求数,则通过CAS修改剩余许可量并返回,如果小于的话,返回小于0的数,表示获取失败。

(2)公平获取 在获取时还会判断。如果当前线程不在队列的头部,则返回-1,排队等候;然后再去判断信号量许可。

3、公平信号量的释放

调用如下方法来释放信号量许可,如下:

1<span style="color: #0000ff;">public <span style="color: #0000ff;">void release(<span style="color: #0000ff;">int<span style="color: #000000;"> permits) {
<span style="color: #0000ff;">if (permits < 0) <span style="color: #0000ff;">throw <span style="color: #0000ff;">new<span style="color: #000000;"> IllegalArgumentException();
sync.releaseShared(permits);
}

调用无参数的release()方法默认只释放一个信号量许可,而下面的可以指定:

releaseShared(

首先调用tryReleaseShared()方法去释放,源代码如下:

tryReleaseShared( current = next = current + (next < current) Error("Maximum permit count exceeded"

如果tryReleaseShared()尝试释放共享锁失败,则会调用doReleaseShared()去释放共享锁。doReleaseShared()的源码如下

Node h = (h != && h != ws = (ws == (!compareAndSetWaitStatus(h,Node.SIGNAL,0 (ws == 0 && !compareAndSetWaitStatus(h,0; (h == head)

4、非公平信号量的释放

tryAcquireShared( nonfairTryAcquireShared( available = remaining = available -=0,则设置可以获得的信号量许可数为remaining (remaining < 0 ||

举个例子,如下:

<span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> SemaphoreTest1 {
<span style="color: #0000ff;">private
<span style="color: #0000ff;">static
<span style="color: #0000ff;">final <span style="color: #0000ff;">int SEM_MAX = 10<span style="color: #000000;">;
<span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) {
Semaphore sem = <span style="color: #0000ff;">new<span style="color: #000000;"> Semaphore(SEM_MAX);
<span style="color: #008000;">//<span style="color: #008000;">创建线程池
ExecutorService threadPool = Executors.newFixedThreadPool(3<span style="color: #000000;">);
<span style="color: #008000;">//<span style="color: #008000;">在线程池中执行任务
threadPool.execute(<span style="color: #0000ff;">new MyThread(sem,5<span style="color: #000000;">));
threadPool.execute(<span style="color: #0000ff;">new MyThread(sem,4<span style="color: #000000;">));
threadPool.execute(<span style="color: #0000ff;">new MyThread(sem,7<span style="color: #000000;">));
<span style="color: #008000;">//<span style="color: #008000;">关闭池
<span style="color: #000000;"> threadPool.shutdown();
}
}

<span style="color: #0000ff;">class MyThread <span style="color: #0000ff;">extends<span style="color: #000000;"> Thread {
<span style="color: #0000ff;">private <span style="color: #0000ff;">volatile Semaphore sem; <span style="color: #008000;">//<span style="color: #008000;"> 信号量
<span style="color: #0000ff;">private <span style="color: #0000ff;">int count; <span style="color: #008000;">//<span style="color: #008000;"> 申请信号量的大小
<span style="color: #000000;">
MyThread(Semaphore sem,<span style="color: #0000ff;">int<span style="color: #000000;"> count) {
<span style="color: #0000ff;">this.sem =<span style="color: #000000;"> sem;
<span style="color: #0000ff;">this.count =<span style="color: #000000;"> count;
}

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; run() {
    </span><span style="color: #0000ff;"&gt;try</span><span style="color: #000000;"&gt; {
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 从信号量中获取count个许可</span>

<span style="color: #000000;"> sem.acquire(count);

        Thread.sleep(</span>2000<span style="color: #000000;"&gt;);
        System.out.println(Thread.currentThread().getName() </span>+ " acquire count="+<span style="color: #000000;"&gt;count);
    } </span><span style="color: #0000ff;"&gt;catch</span><span style="color: #000000;"&gt; (InterruptedException e) {
        e.printStackTrace();
    } </span><span style="color: #0000ff;"&gt;finally</span><span style="color: #000000;"&gt; {
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 释放给定数目的许可,将其返回到信号量。</span>

<span style="color: #000000;"> sem.release(count);
System.out.println(Thread.currentThread().getName() + " release " + count + ""<span style="color: #000000;">);
}
}
}

某一次运行后的结果如下:

pool-1-thread-1 acquire count=5-1-thread-2 acquire count=4-1-thread-1 release 5-1-thread-2 release 4-1-thread-3 acquire count=7-1-thread-3 release 7

原文地址:http://www.2cto.com/kf/201402/278471.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读