Semaphore

semaphore翻譯為信號(hào)量,它用來(lái)做什么用呢?——看JDK文檔:

Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource. For example, here is a class that uses a semaphore to control access to a pool of items:

由這段英文可知,semaphore是限制線程數(shù)量的,原因往往是資源有限。接著JDK文檔舉了一個(gè)例子铐姚,由semaphore來(lái)限制對(duì)象池的訪問。對(duì)象池的大小是固定的肛捍,其中資源的訪問需要限制隐绵。

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;
   } 

對(duì)象池中的對(duì)象數(shù)量是100,所以semaphore的初始值也是100拙毫。獲取對(duì)象之前依许,必須通過semaphore的通過。getNextAvailableItem()被synchronized修飾缀蹄,這是防止并發(fā)情況下峭跳,返回同一個(gè)對(duì)象膘婶,并且標(biāo)記對(duì)象的使用狀態(tài)。歸還對(duì)象池中對(duì)象時(shí)蛀醉,需要增加semaphore的值availablePermits()悬襟。

這段代碼也可以看到Pool的設(shè)計(jì)思想。

想到2016年遇到的一道面試題拯刁,假設(shè)有N個(gè)線程古胆,依次打印0, 1, 2, N-1, N, N+1, N+2 ...

2N-1……

審題可知,這道題主要考察多線程之間的同步筛璧。多個(gè)線程之間循環(huán)同步,而且輸出保持有序性惹恃,可知每次輸出只能有一個(gè)線程打印夭谤,這里剛好遇到semaphore.

class Worker4 implements Runnable {
    private int x;
    private int co;
    Semaphore semaphore;

    public Worker4(int x, int co, Semaphore semaphore) {
        this.x = x;
        this.co = co;
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        while (x < 1000) {
            try {
                semaphore.acquire();
                if (x == ConditionTest.n + 1) {
                    System.out.println(Thread.currentThread().getName() + "\t" + (++ConditionTest.n));
                    x += co;
                }
                semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(1, false);
        System.out.println(semaphore.availablePermits());
        // n 是線程數(shù)量
        int n = ThreadLocalRandom.current().nextInt(10, 20);
        for (int i = 0; i < n; i++) {
            Thread thread = new Thread(new Worker4(i, n, semaphore));
            thread.start();
        }
}

2019-07-18
為什么要用兩個(gè)“鎖”?這個(gè)問題巫糙,我很早就覺察了±嗜澹現(xiàn)在重看代碼才明白。
內(nèi)部鎖是必須的参淹,因?yàn)橐驗(yàn)間et 和 put 都不是原子操作醉锄。
信號(hào)量是為了控制線程數(shù)量的,這樣只會(huì)讓少量的線程去競(jìng)爭(zhēng)內(nèi)部鎖浙值。
如果沒有信號(hào)量恳不,那所有的線程都會(huì)搶占內(nèi)部鎖,這無(wú)疑是不合理的开呐。
所以烟勋,信號(hào)量有限流的作用。

參考資料:Semaphore (Java Platform SE 8 )

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末筐付,一起剝皮案震驚了整個(gè)濱河市卵惦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瓦戚,老刑警劉巖沮尿,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異较解,居然都是意外死亡畜疾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門哨坪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)庸疾,“玉大人,你說我怎么就攤上這事当编〗齑龋” “怎么了徒溪?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)金顿。 經(jīng)常有香客問我臊泌,道長(zhǎng),這世上最難降的妖魔是什么揍拆? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任渠概,我火速辦了婚禮,結(jié)果婚禮上嫂拴,老公的妹妹穿的比我還像新娘播揪。我一直安慰自己,他們只是感情好筒狠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布猪狈。 她就那樣靜靜地躺著,像睡著了一般辩恼。 火紅的嫁衣襯著肌膚如雪雇庙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天灶伊,我揣著相機(jī)與錄音疆前,去河邊找鬼。 笑死聘萨,一個(gè)胖子當(dāng)著我的面吹牛竹椒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播匈挖,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼碾牌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了儡循?” 一聲冷哼從身側(cè)響起舶吗,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎择膝,沒想到半個(gè)月后誓琼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肴捉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年腹侣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片齿穗。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡傲隶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窃页,到底是詐尸還是另有隱情跺株,我是刑警寧澤复濒,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站乒省,受9級(jí)特大地震影響巧颈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜袖扛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一砸泛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛆封,春花似錦唇礁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至妒蛇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間楷拳,已是汗流浹背绣夺。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留欢揖,地道東北人陶耍。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像她混,于是被迫代替她去往敵國(guó)和親烈钞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354