鍍金池/ 問答/Java  Linux/ Java:緩沖行(cache line)的一些問題

Java:緩沖行(cache line)的一些問題

對緩沖行我還有些地方不太理解,
1 緩存一致性下緩沖行失效是不是僅針對volatile,如果不是volatile變量應該不會有這種問題吧?
2 具體實踐的時候,什么情況下才進行緩沖行填充?所有高并發(fā)情況下成員volatile變量頻繁寫的類都要進行緩沖行填充嗎?都要使用disruptor框架?

回答
編輯回答
撥弦

準確來說確實不是針對volatile,而是解決了volatile內(nèi)存可見性帶來的false sharing問題的。如果不是volatile這種問題應該不會存在。

具體實踐中,也是一般針對基本數(shù)據(jù)類型的volatile比較合適,因為行緩沖中的cache line的大小一般也就只有64字節(jié)而已。

除了disruptor框架,你可以查看hystrix和java8中的Long adder

2018年5月13日 09:24
編輯回答
風畔

前幾天剛看了幾篇相關文章,說一下我的理解吧,權作交流,有不對的地方還請指正。

首先說說我對題目中的幾個相關重要概念的理解:

  1. 緩存一致性是指的由于CPU緩存的存在導致的并發(fā)訪問時多個CPU緩存中的數(shù)據(jù)不一致的問題。
  2. volatile關鍵字是在java中使用內(nèi)存屏障來解決緩存一致性問題的方式。
  3. 緩存行是CPU本身優(yōu)化緩存使用效率的一種機制,也即從內(nèi)存到CPU緩存的數(shù)據(jù)操作是以行為單位的,這一行中可能包含多個變量,而由于該機制,結合MESI協(xié)議,當并發(fā)操作同一行的不同變量的時候就會產(chǎn)生偽共享問題,也即對不同變量的操作卻產(chǎn)生了競爭問題有了同步鎖,這種不必要的鎖當然會影響性能。

然后,針對題主的問題,說說我的看法:

  1. volatile是用于解決緩存一致性問題,因為volatile實際上只是保證了對CPU緩存的操作立即flush到內(nèi)存,此時的flush依然是以緩存行為單位的,也即你對某緩存行中的單個變量的volatile實際上是應用到了整個緩存行的所有變量,進而會有不同變量的不必要的操作同步,影響性能,此時便需要解決這個問題。
  2. 緩存行填充就是為了解決偽共享產(chǎn)生的性能問題的,實現(xiàn)方式是使用無用變量填充掉特定行多余部分。所以具體實現(xiàn)的時候,我認為一般情況下,為了性能上的考慮,對volatile變量最好還是應用緩存行填充,而高并發(fā)寫情況下那是毋庸置疑必須進行填充,否則偽共享問題就真的成了他們所說的“性能殺手”了。
  3. 而不在volatile的情況下,緩存行依然存在,只不過若沒有涉及到并發(fā)寫,就不會有偽共享問題,但如果涉及到并發(fā)寫,又會用volatile來解決緩存一致性問題。所以從這個角度來說,volatile也算是與緩存行填充一一對應。但有一點還是有必要分清楚,緩存行其實并不與volatile直接關聯(lián),而是與同一緩存行中不同變量的并發(fā)寫直接關聯(lián),volatile是解決并發(fā)寫,緩存行填充是解決并發(fā)寫時flush緩存行產(chǎn)生的偽共享性能問題。

最后總結一下題主兩個問題的答案:

  1. 緩存一致性是一個需要解決的問題,volatile緩存行填充是解決兩個不同但有一定關聯(lián)關系的問題的方式,如果沒有并發(fā)寫,也就沒有緩存一致性問題,也就不需要volatile和緩存行填充了
  2. 緩存行填充是為了解決偽共享問題,理論上來說,所有并發(fā)寫入同一緩存行的不同變量的操作都會產(chǎn)生偽共享問題,高并發(fā)下volatile變量頻繁寫肯定需要進行緩存行填充。至于disruptor框架,不巧我還不是很了解,但如果你能手動進行緩存行填充的話,也不是必須要用吧?
2017年8月12日 22:29