天天看點

head_和tail_還有後面的變量中加添加了無意義的字段P0、P1和P2,因為head_和tail_頻繁變化,目的是防

作者:從頭開始自學java

head_ 和 tail_ 還有後面的變量中加添加了無意義的字段 P0、P1 和 P2 ,因為 head_ 和 tail_ 頻繁變化,目的是防止出現前面講過的僞共享導緻性能下降問題。

構造函數中強制傳入的隊列大小(size)必須為 2 的幂數,目的是想用 & 而不是 % 取模,因為 & 比 % 快 2ns,最求極緻性能。

Push 和 Pop 函數中讀寫操作是否需要增加記憶體屏障,讀寫操作可以抽象描述如下表格:

在讀寫操作亂序的 CPU 上可以出現上述情況,會導出線 Bug,解釋一下:

當剛初始化的隊列,隊列還是空的,這時核心0 執行 Push 函數,同時核心1 執行 Pop 函數;

Push 裡的條件(tail <= head ? tail + size_ <= head + 1 : tail <= head + 1)為 true,表示隊列已經滿了,是以生産失敗,其實隊列還是空的;

Pop 裡的條件(tail == head_ || !valid_[tail])為 false,表示隊列有資料,并且消費 tail 位置資料,實際上 tail 位置還沒資料;

導緻生産和消費都發生了錯誤。

解決辦法是添加讀寫屏障(LoadStore barrier)

在 Arm 等亂序執行的平台上可以解決問題;幸好 x86-TSO 平台上讀操作不能延後,也就不需要讀寫屏障,手動加了也是空操作(no-op)。

head_和tail_還有後面的變量中加添加了無意義的字段P0、P1和P2,因為head_和tail_頻繁變化,目的是防
head_和tail_還有後面的變量中加添加了無意義的字段P0、P1和P2,因為head_和tail_頻繁變化,目的是防
head_和tail_還有後面的變量中加添加了無意義的字段P0、P1和P2,因為head_和tail_頻繁變化,目的是防
head_和tail_還有後面的變量中加添加了無意義的字段P0、P1和P2,因為head_和tail_頻繁變化,目的是防
head_和tail_還有後面的變量中加添加了無意義的字段P0、P1和P2,因為head_和tail_頻繁變化,目的是防

繼續閱讀