【Java8原始碼分析】併發包-Semaphore
Semaphore是訊號量,它的作用是控制多個允許。
打個比方,一個博物館有容納1000人的能力(Semaphore的允許是1000),假如1500人同時來參館,只有1000人能獲得允許入館(獲得鎖),其餘的500則需排隊(阻塞),直到館內的人離開(釋放鎖)才能放人入館。
1 如何使用
public class SemaphoreDemo {
public static void main(String[] args) {
for (int i = 0; i < 4; i++) {
new Thread(new SemaphoreTest()).start();
}
}
static class SemaphoreTest implements Runnable{
public static Semaphore semaphore = new Semaphore(2, true);
@Override
public void run() {
try {
semaphore.acquire();
System.out.println(Thread.currentThread() + " getting semaphore");
Thread.sleep(1000 );
System.out.println(Thread.currentThread() + " realsing semaphore");
semaphore.release();
} catch (Exception e) {
}
}
}
}
程式輸出
Thread[Thread-1,5,main] getting semaphore
Thread[Thread-0,5,main] getting semaphore
Thread[Thread-0,5 ,main] realsing semaphore
Thread[Thread-1,5,main] realsing semaphore
Thread[Thread-3,5,main] getting semaphore
Thread[Thread-2,5,main] getting semaphore
Thread[Thread-2,5,main] realsing semaphore
Thread[Thread-3,5,main] realsing semaphore
2 原始碼分析
Semaphore
與ReetrantLock
一樣有公平鎖與非公平鎖,ReetrantLock
可以看成是Semaphore
許可為1的特例,在實現中,Semaphore
中的state
代表可用的許可,在ReetrantLock
中,state
大於0代表執行緒重入的次數
2.1 非公平鎖
(1)獲取許可
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
remaining表示請求許可後的許可剩餘值,如果
- remaining < 0,許可不足,掛起執行緒,並且新增執行緒至排隊佇列
- remaining > 0,自旋嘗試更新state值,更新成功獲得許可
從程式碼可以看到,當一個執行緒申請許可時,無需判斷是否有執行緒在排隊佇列中,體現非公平性
(2)釋放許可
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
if (compareAndSetState(current, next))
return true;
}
}
自旋採用CAS演算法更新state狀態
2.2 公平鎖
(1)獲取許可
protected int tryAcquireShared(int acquires) {
for (;;) {
// 先判斷排隊佇列中是否為空
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
公平鎖的機制比非公平鎖多了判斷排隊佇列是否為空,如果有其他執行緒在排隊佇列中,則該執行緒也需轉入排隊佇列,體現公平性。
3 總結
- Semaphore是不可重入的,同一執行緒多次獲取Semaphore是會消耗許可的,例如一個Semaphore的許可為2,同一執行緒呼叫了3次acquire函式,該執行緒會被阻塞
參考
相關推薦
【Java8原始碼分析】NIO包-FileChannel
1 概述 Java NIO 由以下幾個核心部分組成: Buffer Channel Selectors 相關類的使用方法可以參考Java NIO 系列教程,寫的通俗易懂。 本文主要從原始碼方面分析一下Channel類。
【Java8原始碼分析】NIO包-Selector選擇器
1 概述 Java NIO 由以下幾個核心部分組成: Buffer Channel Selectors 相關類的使用方法可以參考Java NIO 系列教程,寫的通俗易懂。 本文主要從原始碼方面分析一下Selector選擇器。關
【Java8原始碼分析】併發包-Semaphore
Semaphore是訊號量,它的作用是控制多個允許。 打個比方,一個博物館有容納1000人的能力(Semaphore的允許是1000),假如1500人同時來參館,只有1000人能獲得允許入館(獲得鎖),其餘的500則需排隊(阻塞),直到館內的人離開(釋
【Java8原始碼分析】併發包-AtomicInteger
AtomicInteger類是實現了原子操作的Integer,以往對於保證int、double、float等基礎型別的運算原子性,需要採用加鎖的方式。但是為了一個簡單的運算操作採用鎖,在多執行緒競爭嚴重的情況下,會導致效能降低,所以在java1.5推出了Atom
【Java8原始碼分析】併發包-ConcurrentHashMap(一)
一、CAS原理簡介 Java8中,ConcurrentHashMap摒棄了Segment的概念,而是啟用了一種全新的方式實現:利用CAS演算法。它沿用了HashMap的思想,底層依然由“陣列”+連結串列+紅黑樹的方式實現。 那什麼CAS演算法呢?以前採用鎖的
【Java8原始碼分析】集合框架-HashMap
一、HashMap的儲存結構 總共有兩種儲存類 // 1. 雜湊衝突時採用連結串列法的類,一個雜湊桶多於8個元素改為TreeNode static class Node<K,V> implements Map.Entry<K,V> /
【Java8原始碼分析】執行緒-Thread類的全面剖析
一、基本知識 (1)執行緒特性 每個執行緒均有優先順序 執行緒能被標記為守護執行緒 每個執行緒均分配一個name (2)建立執行緒的方法 繼承Thread類,並重現run方法 // 繼承Thread類 class PrimeThread e
【Java8原始碼分析】執行緒-ThreadLocal的全面剖析
一、背景 ThreadLocal類顧名思義就是,申明為ThreadLocal的變數,對於不同執行緒來說都是獨立的。 下面是一個例子: public class Test { public static void main(String[] a
【go原始碼分析】go原始碼之slice原始碼分析
Go 語言切片是對陣列的抽象。 Go 陣列的長度不可改變,與陣列相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。 len() 和 cap() 函式 切片是可索引的,並且可以由 len() 方法獲取長度。
【go原始碼分析】go原始碼之list原始碼分析
本文針對go 1.11版本,路徑src/container/list/list.go 資料結構 Element結構體 Value 前驅 後繼 // Element is an element of a linked list. type Element st
【轉】【java原始碼分析】Map中的hash演算法分析
全網把Map中的hash()分析的最透徹的文章,別無二家。 2018年05月09日 09:08:08 閱讀數:957 你知道HashMap中hash方法的具體實現嗎?你知道HashTable、ConcurrentHashMap中hash方法
【spring原始碼分析】IOC容器初始化(二)
前言:在【spring原始碼分析】IOC容器初始化(一)中已經分析了匯入bean階段,本篇接著分析bean解析階段。 1.解析bean程式呼叫鏈 同樣,先給出解析bean的程式呼叫鏈: 根據程式呼叫鏈,整理出在解析bean過程中主要涉及的類和相關方法。 2.解析bean原始碼分
【NCNN原始碼分析】1.基本資料型別
對於NCNN而言,核心在於網路的前向推理過程(Inference),其主要資料型別為mat,該資料型別以類的形式定義在src/mat.h中,其中包含了mat的建構函式、解構函式、常見的運算過程。 #if
【Go 原始碼分析】從 sort.go 看排序演算法的工程實踐
go version go1.11 darwin/amd64file: src/sort/sort.go 排序演算法有很多種類,比如快排、堆排、插入排序等。各種排序演算法各有其優劣性,在實際生產過程中用到的排序演算法(或者說 Sort 函式)通常是由幾種排序演算法組
【PHP7原始碼分析】如何理解PHP虛擬機器(一)
順風車運營研發團隊 李樂 1.從物理機說起 虛擬機器也是計算機,設計思想和物理機有很多相似之處; 1.1馮諾依曼體系結構 馮·諾依曼是當之無愧的數字計算機之父,當前計算機都採用的是馮諾依曼體系結構;設計思想主要包含以下幾個方面: 指令和資料不加區別混合儲存在同一個儲
【Mybatis原始碼分析】13-記一次PageHelper reasonable引數使用不當造成的死迴圈
問題描述及原因 使用Mybatis PageHelper外掛做了表的分頁查詢,要求查詢符合某一條件的所有記錄做處理,就寫了一個迭代器在while迴圈裡對每條記錄做處理,直到符合條件的記錄都處理完程式返回。程式碼如下 public class ReconPaymentI
【Tomcat9原始碼分析】元件與框架概述
1 元件與框架介紹 Server:代表整個Catalina Servlet容器,可以包含一個或多個Service Service:包含Connector和Container的集合,Service用適當的Connector接收使用者的請求,
【E2LSH原始碼分析】p穩定分佈LSH演算法初探
上一節,我們分析了LSH演算法的通用框架,主要是建立索引結構和查詢近似最近鄰。這一小節,我們從p穩定分佈LSH(p-Stable LSH)入手,逐漸深入學習LSH的精髓,進而靈活應用到解決大規模資料的
【MyBatis原始碼分析】TypeHandler解析屬性配置元素詳述及相關列舉使用高階進階
TypeHandler解析接著看一下typeHandlerElement(root.evalNode("typeHandlers"));方法,這句讀取的是<configuration>下的<typeHandlers>節點,程式碼實現為:private
【proxyConfig原始碼分析】【proxyTargetClass】【exposeProxy】
本文轉載自shysheng:spring proxyConfig原始碼分析 我們知道,ProxyConfig是所有產生Spring AOP代理物件的基類,它是一個配置源,主要為其AOP代理物件工廠實現類提供基本的配置屬性。 它一共包含5個屬性,本文主要就是分析這5個屬性在產生代理物件過