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,最終會賦值到AbstractQueuedSynchronizer的state欄位,這個欄位的ReentrantLock中是用來計算鎖重入的。但是在Semaphore裡面欄位是用來控制資源訪問數量的。
1.acquire方法獲取的許可的時候 先去扣減,將state的值-1,如果結果不小於0,就通過CAS操作修改state的值,最後返回當前剩餘許可
2. 如果返回的許可剩餘數量小於0 就執行doAcquireSharedInterruptibly方法,將當前執行緒以共享的模式加入到隊列中去,再將執行緒掛起
3.release方法 釋放許可 CAS操作將state的值+1
4.設置成功了執行doReleaseShared方法,去喚醒隊列中等待的執行緒,獲取到許可執行