semaphore
semaphore翻譯為信號量,它用來做什麼用呢?——看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是限制線程數量的,原因往往是資源有限。接著JDK文檔舉了一個例子,由semaphore來限制對象池的訪問。對象池的大小是固定的,其中資源的訪問需要限制。
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; }
對象池中的對象數量是100,所以semaphore的初始值也是100。獲取對象之前,必須通過semaphore的通過。getNextAvailableItem()被synchronized修飾,這是防止並發情況下,返回同一個對象,並且標記對象的使用狀態。歸還對象池中對象時,需要增加semaphore的值availablePermits()。
這段代碼也可以看到Pool的設計思想。
想到2016年遇到的一道面試題,假設有N個線程,依次列印0, 1, 2, N-1, N, N+1, N+2 ...
2N-1……
審題可知,這道題主要考察多線程之間的同步。多個線程之間循環同步,而且輸出保持有序性,可知每次輸出只能有一個線程列印,這裡剛好遇到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() + " " + (++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 是線程數量 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(); }}
參考資料:Semaphore (Java Platform SE 8 )
推薦閱讀:
※CyclicBarrier
※Mutex and Spinlock
TAG:並發 |