Semaphore和AQS

Semaphore意思的訊號量,它的作用是控制訪問特定資源的執行緒數量

構造方法

public Semaphore(int permits)

public Semaphore(int permits, boolean fair)

  permits:允許同時訪問的執行緒數量

  fair:是否公平,若true的話,下次執行的會是先進去等待的執行緒(先入先出)

 

使用

acquire():獲取許可執行

release():釋放許可,讓其他執行緒獲取許可執行。

 

顯然這個功能可以用於資源訪問控制或者是限流的操作。

 

如下程式碼每次只會有兩個執行緒執行。

package com.nijunyang.concurrent;

import java.util.concurrent.Semaphore;

/**
 * Description:
 * Created by nijunyang on 2020/5/13 23:31
 */
public class SemaphoreTest {
    Semaphore semaphore;

    public SemaphoreTest(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    public static void main(String[] args) {
        SemaphoreTest semaphoreTest = new SemaphoreTest(new Semaphore(2, true));
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                try {
                    semaphoreTest.test();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "執行緒" + i);
            thread.start();
        }
        System.out.println("執行緒創建完畢.");
    }

    public void test() throws InterruptedException {
        semaphore.acquire();
        System.out.println(Thread.currentThread().getName() + "執行.");
        Thread.sleep(4000);
        semaphore.release();
    }
}

 

原理

進入Semaphore的程式碼一看,又見到AQS,前面ReentrantLock中用到的是獨佔模式,Semaphore中就是共享模式了。和ReentrantLock如出一轍,內部類Sync繼承了AbstractQueuedSynchronizer,同時有兩個子類實現一個公平FairSync,另一個非公平NonfairSync

構造方法傳入的permits,最終會賦值到AbstractQueuedSynchronizerstate欄位,這個欄位的ReentrantLock中是用來計算鎖重入的。但是在Semaphore裡面欄位是用來控制資源訪問數量的。

 

1.acquire方法獲取的許可的時候 先去扣減,將state的值-1,如果結果不小於0,就通過CAS操作修改state的值,最後返回當前剩餘許可

 

 

 2. 如果返回的許可剩餘數量小於0 就執行doAcquireSharedInterruptibly方法,將當前執行緒以共享的模式加入到隊列中去,再將執行緒掛起

 

 

3.release方法 釋放許可  CAS操作將state的值+1

 

 4.設置成功了執行doReleaseShared方法,去喚醒隊列中等待的執行緒,獲取到許可執行