基於ThreadLocal的無鎖併發發號器實現

2021-08-28 13:36:36 字數 1542 閱讀 2524

threadlocal是乙個執行緒級別的變數副本,它是對於執行緒隔離的,各個執行緒之間不能訪問非自己的threadlocal變數。

我們先來分析一下乙個優秀的id應該具備哪些特點?

為了保證id的全域性唯一,在生成的時候我們應該對其做一些併發安全的處理,不然很可能就會出現重複id,比如說id的序列號是遞增的,那麼如何去保證在多執行緒訪問情況下生成的id不重複呢?

我們最先想到的方式就是加鎖,每次只允許乙個執行緒去操作這個累加的變數,這樣自然是能夠做到的,但是鎖競爭會帶來額外的效能開銷,那有沒有不加鎖的方式可以保證在多執行緒的情況下生成唯一id呢?答案是肯定的,接下來我們看看如何使用threadlocal來實現無鎖化併發程式設計。

在發號器中最核心的**就是id序列號的生成,在本文中我也僅僅是對這一段進行分析(完整專案點這兒)

打個比方假如我們能夠生成100個id,1~100,我們有兩個執行緒,第乙個執行緒只生成1,3,5…這樣的id,第二個執行緒只生成2,4,6…這樣的id,從理論上來說,這樣的併發是不會重複的。

那麼我們的問題就轉化成了如何去分配生成的id段,話不多說,直接上**講解吧

public

class

sender};

//用執行緒id作為起始值

private

static

final threadlocal

target=

newthreadlocal

()};

//用執行緒池中的執行緒去生成id

private

static future

doget()

);}public

static

long

get(

)catch

(interruptedexception e)

catch

(executionexception e)

return0;

}}

我們來測試一下是否會出現重複id

public

class

test

catch

(interruptedexception e)

catch

(brokenbarrierexception e)

//把生成的id放到set中去

for(

int j =

0; j <

1000000

; j++)}

).start()

;}//主線程睡眠20s等待程式跑完

thread.

sleep

(20000);

//輸出id個數,如果size==執行緒數*單個執行緒生成的id數則認為是執行緒安全的

system.out.

println

(set.

size()

);}}

結果如下

10000000

通過這種為執行緒劃分工作範圍的方式,我們可以利用threadlocal做到無鎖化的併發程式設計

聊聊ThreadLocal原始碼 基於JDK1 8

原文 主要方法 public t get return setinitialvalue public void set t value 下面 時樓主認為threadlocal中比較重要的,還是比較容易看懂的,就不在一一細說 public class threadlocal 除非執行緒先前呼叫了方法,...

關於無鎖佇列(基於陣列)

鎖的底層必然有著原子操作,而其設計為通用場景使用,我們拋棄鎖的使用,直接從更細粒度來使用原子操作確保佇列的一致性 稱為無鎖佇列 什麼樣的佇列可以支援併發的多生產者多消費者?確保併發的copy過程互不影響 確保併發的指標更新操作原子不丟失。指標操作無非是值的操作,不存在順序問題 如何確保上述兩點?最粗...

基於PCDN技術的無延時直播方案

摘要 2018亞太cdn峰會在北京隆重召開,在4月12日上午的運營商論壇中,阿里雲邊緣計算團隊高階技術專家張士波進行了 基於pcdn技術的無延時直播方案 的主題演講。本文為演講內容。當大家談到直播,一般很驚訝於直播近幾年來發展的規模,尤其是2016到2017年直播使用者增長速度達到了22.6 使用者...