日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Semaphore应用及原理

發(fā)布時(shí)間:2024/4/13 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Semaphore应用及原理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

信號量Semaphore的介紹

我們以一個(gè)停車場運(yùn)作為例來說明信號量的作用。假設(shè)停車場只有三個(gè)車位,一開始三個(gè)車位都是空的。這時(shí)如果同時(shí)來了三輛車,看門人允許其中它們進(jìn)入進(jìn)入,然后放下車攔。以后來的車必須在入口等待,直到停車場中有車輛離開。這時(shí),如果有一輛車離開停車場,看門人得知后,打開車攔,放入一輛,如果又離開一輛,則又可以放入一輛,如此往復(fù)。

在這個(gè)停車場系統(tǒng)中,車位是公共資源,每輛車好比一個(gè)線程,看門人起的就是信號量的作用。信號量是一個(gè)非負(fù)整數(shù),表示了當(dāng)前公共資源的可用數(shù)目(在上面的例子中可以用空閑的停車位類比信號量),當(dāng)一個(gè)線程要使用公共資源時(shí)(在上面的例子中可以用車輛類比線程),首先要查看信號量,如果信號量的值大于1,則將其減1,然后去占有公共資源。如果信號量的值為0,則線程會將自己阻塞,直到有其它線程釋放公共資源。

在信號量上我們定義兩種操作: acquire(獲取) 和 release(釋放)。當(dāng)一個(gè)線程調(diào)用acquire操作時(shí),它要么通過成功獲取信號量(信號量減1),要么一直等下去,直到有線程釋放信號量,或超時(shí)。release(釋放)實(shí)際上會將信號量的值加1,然后喚醒等待的線程。
信號量主要用于兩個(gè)目的,一個(gè)是用于多個(gè)共享資源的互斥使用,另一個(gè)用于并發(fā)線程數(shù)的控制。

示例

Semaphore包含公平鎖與非公平鎖2種實(shí)現(xiàn)

非公平鎖

package main.java.study; import java.util.Calendar; import java.util.Date; import java.util.concurrent.*;public class SemaphoreDemo {final static Semaphore sema = new Semaphore(5);public static class Runner implements Runnable{int i;public Runner(int i){this.i = i;}@Overridepublic void run() {try{sema.acquire();Thread.sleep(1000);System.out.println( "Runner【" + i + "】:" + new Date().toString() + " done!");}catch ( InterruptedException ex){ex.printStackTrace();}sema.release();}}public static void main (String[] args){ExecutorService service = Executors.newFixedThreadPool(10);for(int i = 0 ;i < 20;i++){service.execute(new Runner(i));}} }

結(jié)果如下:

Runner【2】:Sat May 25 14:27:55 CST 2019 done!
Runner【0】:Sat May 25 14:27:55 CST 2019 done!
Runner【4】:Sat May 25 14:27:55 CST 2019 done!
Runner【3】:Sat May 25 14:27:55 CST 2019 done!
Runner【1】:Sat May 25 14:27:55 CST 2019 done!
Runner【10】:Sat May 25 14:27:56 CST 2019 done!
Runner【12】:Sat May 25 14:27:56 CST 2019 done!
Runner【11】:Sat May 25 14:27:56 CST 2019 done!
Runner【13】:Sat May 25 14:27:56 CST 2019 done!
Runner【14】:Sat May 25 14:27:56 CST 2019 done!
Runner【5】:Sat May 25 14:27:57 CST 2019 done!
Runner【15】:Sat May 25 14:27:57 CST 2019 done!
Runner【7】:Sat May 25 14:27:57 CST 2019 done!
Runner【18】:Sat May 25 14:27:57 CST 2019 done!
Runner【19】:Sat May 25 14:27:57 CST 2019 done!
Runner【9】:Sat May 25 14:27:58 CST 2019 done!
Runner【6】:Sat May 25 14:27:58 CST 2019 done!
Runner【16】:Sat May 25 14:27:58 CST 2019 done!
Runner【17】:Sat May 25 14:27:58 CST 2019 done!
Runner【8】:Sat May 25 14:27:58 CST 2019 done!

?公平鎖

package main.java.study; import java.util.Calendar; import java.util.Date; import java.util.concurrent.*;public class SemaphoreDemo {final static Semaphore sema = new Semaphore(5,true);public static class Runner implements Runnable{int i;public Runner(int i){this.i = i;}@Overridepublic void run() {try{sema.acquire();Thread.sleep(1000);System.out.println( "Runner【" + i + "】:" + new Date().toString() + " done!");}catch ( InterruptedException ex){ex.printStackTrace();}sema.release();}}public static void main (String[] args){ExecutorService service = Executors.newFixedThreadPool(10);for(int i = 0 ;i < 20;i++){service.execute(new Runner(i));}} }

結(jié)果如下:

Runner【2】:Sat May 25 14:33:49 CST 2019 done!
Runner【1】:Sat May 25 14:33:49 CST 2019 done!
Runner【3】:Sat May 25 14:33:49 CST 2019 done!
Runner【0】:Sat May 25 14:33:49 CST 2019 done!
Runner【4】:Sat May 25 14:33:49 CST 2019 done!
Runner【5】:Sat May 25 14:33:51 CST 2019 done!
Runner【6】:Sat May 25 14:33:51 CST 2019 done!
Runner【8】:Sat May 25 14:33:51 CST 2019 done!
Runner【9】:Sat May 25 14:33:51 CST 2019 done!
Runner【7】:Sat May 25 14:33:51 CST 2019 done!
Runner【10】:Sat May 25 14:33:53 CST 2019 done!
Runner【12】:Sat May 25 14:33:53 CST 2019 done!
Runner【11】:Sat May 25 14:33:53 CST 2019 done!
Runner【13】:Sat May 25 14:33:53 CST 2019 done!
Runner【14】:Sat May 25 14:33:53 CST 2019 done!
Runner【15】:Sat May 25 14:33:55 CST 2019 done!
Runner【17】:Sat May 25 14:33:55 CST 2019 done!
Runner【19】:Sat May 25 14:33:55 CST 2019 done!
Runner【16】:Sat May 25 14:33:55 CST 2019 done!
Runner【18】:Sat May 25 14:33:55 CST 2019 done!

源碼

Semaphore:

public Semaphore(int permits) {sync = new NonfairSync(permits);}public Semaphore(int permits, boolean fair) {sync = fair ? new FairSync(permits) : new NonfairSync(permits);}public boolean tryAcquire() {return sync.nonfairTryAcquireShared(1) >= 0;}public boolean tryAcquire(int permits) {if (permits < 0) throw new IllegalArgumentException();return sync.nonfairTryAcquireShared(permits) >= 0;}public void acquire() throws InterruptedException {sync.acquireSharedInterruptibly(1);}public void acquireUninterruptibly() {sync.acquireShared(1);}public void acquire(int permits) throws InterruptedException {if (permits < 0) throw new IllegalArgumentException();sync.acquireSharedInterruptibly(permits);}public void acquireUninterruptibly(int permits) {if (permits < 0) throw new IllegalArgumentException();sync.acquireShared(permits);}//釋放1個(gè)許可public void release() {sync.releaseShared(1);}//釋放指定數(shù)量許可public void release(int permits) {if (permits < 0) throw new IllegalArgumentException();sync.releaseShared(permits);}//減少許可protected void reducePermits(int reduction) {if (reduction < 0) throw new IllegalArgumentException();sync.reducePermits(reduction);}//清空許可public int drainPermits() {return sync.drainPermits();}

Semaphore可以:

  • acqure 1個(gè)或者多個(gè)許可
  • release 1個(gè)或者多個(gè)許可
  • 默認(rèn)是可中斷acquire
  • 默認(rèn)是非公平鎖

Sync:

abstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 1192457210091910933L;Sync(int permits) {setState(permits);}final int getPermits() {return getState();}final int nonfairTryAcquireShared(int acquires) {for (;;) {int available = getState();int remaining = available - acquires;if (remaining < 0 ||compareAndSetState(available, remaining)) 【1】return remaining;}}protected final boolean tryReleaseShared(int releases) {for (;;) {int current = getState();int next = current + releases;if (next < current) // overflowthrow new Error("Maximum permit count exceeded");if (compareAndSetState(current, next))return true;}}final void reducePermits(int reductions) {for (;;) {int current = getState();int next = current - reductions;if (next > current) // underflowthrow new Error("Permit count underflow");if (compareAndSetState(current, next))return;}}final int drainPermits() {for (;;) {int current = getState();if (current == 0 || compareAndSetState(current, 0))return current;}}}

Fair和NoFair

static final class NonfairSync extends Sync {private static final long serialVersionUID = -2694183684443567898L;NonfairSync(int permits) {super(permits);}protected int tryAcquireShared(int acquires) {return nonfairTryAcquireShared(acquires);}}/*** Fair version*/static final class FairSync extends Sync {private static final long serialVersionUID = 2014338818796000944L;FairSync(int permits) {super(permits);}protected int tryAcquireShared(int acquires) {for (;;) {if (hasQueuedPredecessors()) //【2】return -1;int available = getState();int remaining = available - acquires;if (remaining < 0 ||compareAndSetState(available, remaining))return remaining;}}} public final boolean hasQueuedPredecessors() {// The correctness of this depends on head being initialized// before tail and on head.next being accurate if the current// thread is first in queue.Node t = tail; // Read fields in reverse initialization orderNode h = head;Node s;//隊(duì)列為空,或者h(yuǎn)ead節(jié)點(diǎn)后置為null,表示本線程未在等待隊(duì)列return h != t &&((s = h.next) == null //head節(jié)點(diǎn)的后置節(jié)點(diǎn)為null|| s.thread != Thread.currentThread() //或者后置節(jié)點(diǎn)關(guān)聯(lián)線程不為本線程);}

?

比較:

  • 非公平鎖,只要許可滿足就acquire成功(見【1】)
  • 公平鎖,僅當(dāng)本線程在隊(duì)列中沒有前置節(jié)點(diǎn)時(shí),才acquire成功(見【2】)

?

AbstractQueuedSynchronizer源碼參考:https://blog.csdn.net/demon7552003/article/details/90105335

?

?

?

總結(jié)

以上是生活随笔為你收集整理的Semaphore应用及原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。