java線程同步——信號量(Semaphore)

java.util.concurrent.Semaphore

信號量是一種計數器,用來保護一個或者多個共享資源的訪問,它是併發編程的一種基礎工具。

信號量通過計數器的方式來對資源進行訪問控制

當其計數器值大於0時,表示有資源可以訪問

當其計數器值等於0時,線程將進入休眠狀態直到計數器值大於0


通過信號量的構造函數指定資源數量:

private final Semaphore semaphore  = new Semaphore(1);
表示該信號量的計數器值只能爲0或者1,也稱爲二進制信號量

這樣可以限制每次執行的線程只有一個


信號量的使用:

    private final Semaphore semaphore = new Semaphore(1);

    public void a() {
        try {
            //獲取信號量的鎖
            semaphore.acquire();
            //對共享資源進行操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //釋放信號量
            semaphore.release();
        }
    }

信號量也有對應的tryAcquire()方法,和Lock的tryLock()一樣


使用信號量控制資源的多副本併發訪問控制

<pre style="background-color: rgb(255, 255, 255); font-family: Consolas; font-size: 10.5pt;"><pre name="code" class="java">public class TestSemaphore {
    //信號量控制資源的狀態
    private final Semaphore semaphore;
    //資源數組,true表示可用(空閒)
    private boolean[] resources;
    //保護對資源數組的訪問
    private Lock lock;
    //資源數量
    private int resourceCount = 3;

    public TestSemaphore() {
        semaphore = new Semaphore(resourceCount);
        resources = new boolean[resourceCount];
        for (int i = 0; i < resourceCount; i++) {
            resources[i] = true;
        }
        lock = new ReentrantLock();
    }

    public void doSth() {
        try {
            semaphore.acquire();
            int resource = getResource();
            //使用resource進行操作
            //任務完成,把對應的resource置爲空閒
            resources[resource] = true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //釋放信號量
            semaphore.release();
        }
    }

    /**
     * 獲取空閒的資源
     *
     * @return 空閒的資源下標,沒有就返回-1
     */
    private int getResource() {
        //資源下標
        int ret = -1;
        try {
            lock.lock();
            for (int i = 0; i < resources.length; i++) {
                if (resources[i]) {
                    ret = i;
                    resources[i] = false;
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return ret;
    }

}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章