Semaphore 信號(hào)量模型:一個(gè)計(jì)數(shù)器锉桑,一個(gè)等待隊(duì)列铺厨,三個(gè)方法
init():設(shè)置計(jì)數(shù)器的初始值。
down():計(jì)數(shù)器的值減 1颈走;如果此時(shí)計(jì)數(shù)器的值小于 0膳灶,則當(dāng)前線程將被阻塞,否則當(dāng)前線程可以繼續(xù)執(zhí)行立由。
up():計(jì)數(shù)器的值加 1轧钓;如果此時(shí)計(jì)數(shù)器的值小于或者等于 0,則喚醒等待隊(duì)列中的一個(gè)線程拆吆,并將其從等待隊(duì)列中移除聋迎。
這里必須要解釋一下up()方法中計(jì)數(shù)器的值小于或者等于 0的設(shè)定脂矫。需要資源的線程(無論是正在運(yùn)行的枣耀,還是等待的)數(shù)量 = 計(jì)數(shù)器初始值 - 計(jì)數(shù)器當(dāng)前值。? 舉個(gè)例子庭再,計(jì)數(shù)器初始化為2捞奕,兩個(gè)線程進(jìn)入臨界區(qū),此時(shí)計(jì)數(shù)器數(shù)值為0拄轻,很顯然颅围, 2=2-0;再來一個(gè)線程恨搓,down()后計(jì)數(shù)器為-1院促,這個(gè)新來的線程阻塞,此時(shí) 3 = 2 - (-1)斧抱。? 那么接著解釋為什么是小于或等于0.? 反證常拓, 如果計(jì)時(shí)器大于0, 根據(jù)上面計(jì)算公式? 需要資源的線程 = 初始值 - 當(dāng)前值辉浦, 需要資源的線程數(shù)必定小于初始值弄抬,也就是說,資源完全夠用宪郊,根本沒有線程阻塞掂恕,那還喚醒個(gè)錘子拖陆?? ?必須是當(dāng)前值小于等于0才去喚醒
init()、down() 和 up() 三個(gè)方法都是原子性的懊亡,而在Java SDK包中依啰, down()和up()分別對(duì)應(yīng)acquire()和release(),意思也很貼切。
信號(hào)量可以實(shí)現(xiàn)的獨(dú)特功能就是同時(shí)允許多個(gè)線程進(jìn)入臨界區(qū)店枣,但是信號(hào)量不能做的就是同時(shí)喚醒多個(gè)線程去爭(zhēng)搶鎖孔飒,只能喚醒一個(gè)阻塞中的線程,而且信號(hào)量模型是沒有Condition的概念的艰争,即阻塞線程被醒了直接就運(yùn)行了而不會(huì)去檢查此時(shí)臨界條件是否已經(jīng)不滿足了坏瞄,基于此考慮信號(hào)量模型才會(huì)設(shè)計(jì)出只能讓一個(gè)線程被喚醒,否則就會(huì)出現(xiàn)因?yàn)槿鄙貱ondition檢查而帶來的線程安全問題甩卓。正因?yàn)槿笔Я薈ondition鸠匀,所以用信號(hào)量來實(shí)現(xiàn)阻塞隊(duì)列就很麻煩,因?yàn)橐约簩?shí)現(xiàn)類似Condition的邏輯逾柿。
本節(jié)問題:在上面對(duì)象池的例子中缀棍,對(duì)象保存在了 Vector 中,Vector 是 Java 提供的線程安全的容器机错,如果我們把 Vector 換成 ArrayList爬范,是否可以呢?? ?補(bǔ)充:例子中的對(duì)象池弱匪,允許多個(gè)線程同時(shí)訪問青瀑,Semaphore初始化為 大于1的數(shù)。
回答:不可以萧诫。信號(hào)量允許多個(gè)線程訪問資源斥难,尤其是demo中有l(wèi)ist的remove和add操作,這都是先定位再操作的方法帘饶,如果不是線程安全的哑诊,可能會(huì)remove一個(gè)不存在的數(shù)字而出錯(cuò)。add同理及刻。