鍍金池/ 教程/ Java/ 并發(fā)新特性—信號量 Semaphore
并發(fā)新特性—信號量 Semaphore
線程間協(xié)作:wait、notify、notifyAll
notify 通知的遺漏
notifyAll 造成的早期通知問題
多線程的實現(xiàn)方法
深入 Java 內(nèi)存模型(1)
多線程環(huán)境下安全使用集合 API
并發(fā)新特性—Lock 鎖與條件變量
生產(chǎn)者—消費者模型
深入 Java 內(nèi)存模型(2)
線程中斷
Volatile 關(guān)鍵字(上)
并發(fā)新特性—阻塞隊列與阻塞棧
可重入內(nèi)置鎖
守護線程與線程阻塞
并發(fā)新特性—障礙器 CyclicBarrier
Volatile 關(guān)鍵字(下)
synchronized 關(guān)鍵字
synchronized 的另個一重要作用:內(nèi)存可見性
并發(fā)新特性—Executor 框架與線程池
并發(fā)性與多線程介紹
死鎖
實現(xiàn)內(nèi)存可見性的兩種方法比較:synchronized 和 Volatile
線程掛起、恢復(fù)與終止

并發(fā)新特性—信號量 Semaphore

在操作系統(tǒng)中,信號量是個很重要的概念,它在控制進程間的協(xié)作方面有著非常重要的作用,通過對信號量的不同操作,可以分別實現(xiàn)進程間的互斥與同步。當(dāng)然它也可以用于多線程的控制,我們完全可以通過使用信號量來自定義實現(xiàn)類似 Java 中的 synchronized、wait、notify 機制。

Java 并發(fā)包中的信號量 Semaphore 實際上是一個功能完畢的計數(shù)信號量,從概念上講,它維護了一個許可集合,對控制一定資源的消費與回收有著很重要的意義。Semaphore 可以控制某個資源被同時訪問的任務(wù)數(shù),它通過acquire()獲取一個許可,release()釋放一個許可。如果被同時訪問的任務(wù)數(shù)已滿,則其他 acquire 的任務(wù)進入等待狀態(tài),直到有一個任務(wù)被 release 掉,它才能得到許可。

下面給出一個采用 Semaphore 控制并發(fā)訪問數(shù)量的示例程序:

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Semaphore;  
public class SemaphoreTest{  
    public static void main(String[] args) {  
    //采用新特性來啟動和管理線程——內(nèi)部使用線程池  
    ExecutorService exec = Executors.newCachedThreadPool();  
    //只允許5個線程同時訪問  
    final Semaphore semp = new Semaphore(5);  
    //模擬10個客戶端訪問  
    for (int index = 0; index < 10; index++){  
        final int num = index;  
        Runnable run = new Runnable() {  
            public void run() {  
                try {  
                    //獲取許可  
                    semp.acquire();  
                    System.out.println("線程" +   
                        Thread.currentThread().getName() + "獲得許可:"  + num);  
                    //模擬耗時的任務(wù)  
                    for (int i = 0; i < 999999; i++) ;  
                    //釋放許可  
                    semp.release();  
                    System.out.println("線程" +   
                        Thread.currentThread().getName() + "釋放許可:"  + num);  
                    System.out.println("當(dāng)前允許進入的任務(wù)個數(shù):" +  
                        semp.availablePermits());  
                }catch(InterruptedException e){  
                    e.printStackTrace();  
                }  
            }  
        };  
          exec.execute(run);  
    }  
    //關(guān)閉線程池  
    exec.shutdown();  
    }  
}  

某次執(zhí)行的結(jié)果如下:

線程pool-1-thread-1獲得許可:0
線程pool-1-thread-1釋放許可:0
當(dāng)前允許進入的任務(wù)個數(shù):5
線程pool-1-thread-2獲得許可:1
線程pool-1-thread-6獲得許可:5
線程pool-1-thread-4獲得許可:3
線程pool-1-thread-8獲得許可:7
線程pool-1-thread-2釋放許可:1
當(dāng)前允許進入的任務(wù)個數(shù):2
線程pool-1-thread-5獲得許可:4
線程pool-1-thread-8釋放許可:7
線程pool-1-thread-3獲得許可:2
線程pool-1-thread-4釋放許可:3
線程pool-1-thread-10獲得許可:9
線程pool-1-thread-6釋放許可:5
線程pool-1-thread-10釋放許可:9
當(dāng)前允許進入的任務(wù)個數(shù):2
線程pool-1-thread-3釋放許可:2
當(dāng)前允許進入的任務(wù)個數(shù):1
線程pool-1-thread-5釋放許可:4
當(dāng)前允許進入的任務(wù)個數(shù):3
線程pool-1-thread-7獲得許可:6
線程pool-1-thread-9獲得許可:8
線程pool-1-thread-7釋放許可:6
當(dāng)前允許進入的任務(wù)個數(shù):5
當(dāng)前允許進入的任務(wù)個數(shù):3
當(dāng)前允許進入的任務(wù)個數(shù):3
當(dāng)前允許進入的任務(wù)個數(shù):3
線程pool-1-thread-9釋放許可:8
當(dāng)前允許進入的任務(wù)個數(shù):5

可以看出,Semaphore 允許并發(fā)訪問的任務(wù)數(shù)一直為 5,當(dāng)然,這里還很容易看出一點,就是 Semaphore 僅僅是對資源的并發(fā)訪問的任務(wù)數(shù)進行監(jiān)控,而不會保證線程安全,因此,在訪問的時候,要自己控制線程的安全訪問。