Java8的@sun.misc.Contended注解


@sun.misc.Contended 介紹

@sun.misc.Contended 是 Java 8 新增的一個注解,對某字段加上該注解則表示該字段會單獨占用一個緩存行(Cache Line)。

這里的緩存行是指 CPU 緩存(L1、L2、L3)的存儲單元,常見的緩存行大小為 64 字節。

(注:JVM 添加 -XX:-RestrictContended 參數后 @sun.misc.Contended 注解才有效)

單獨使用一個緩存行有什么作用——避免偽共享

為了提高讀取速度,每個 CPU 有自己的緩存,CPU 讀取數據后會存到自己的緩存里。而且為了節省空間,一個緩存行可能存儲着多個變量,即偽共享。但是這對於共享變量,會造成性能問題:

當一個 CPU 要修改某共享變量 A 時會先鎖定自己緩存里 A 所在的緩存行,並且把其他 CPU 緩存上相關的緩存行設置為無效。但如果被鎖定或失效的緩存行里,還存儲了其他不相干的變量 B,其他線程此時就訪問不了 B,或者由於緩存行失效需要重新從內存中讀取加載到緩存里,這就造成了開銷。所以讓共享變量 A 單獨使用一個緩存行就不會影響到其他線程的訪問。

Java 8 之前的方案

在 Java 8 之前,是通過代碼里手動添加屬性的方式解決的,如:

class LongWithPadding {
	long value;
	long p0, p1, p2, p3, p4, p5, p6;
}

一個 long 占 8 個字節,再添加 7 個 long 屬性就會變成 64 個字節,剛好是一個緩存行大小。

但是注意,Java 7 開始 JVM 做優化時可能會把不用的變量給去掉,所以這種方法並不推薦使用。

適用場景

主要適用於頻繁寫共享數據上。如果不是頻繁寫的數據,那么 CPU 緩存行被鎖的幾率就不多,所以沒必要使用了,否則不僅占空間還會浪費 CPU 訪問操作數據的時間。

相關文章

一篇對偽共享、緩存行填充和CPU緩存講的很透徹的文章

Java8使用@sun.misc.Contended避免偽共享


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM