亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

什么是偽共享

發布時間:2021-10-18 14:20:24 來源:億速云 閱讀:89 作者:iii 欄目:web開發

這篇文章主要介紹“什么是偽共享”,在日常操作中,相信很多人在什么是偽共享問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”什么是偽共享”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

什么是偽共享

首先大家都知道,隨著CPU和內存的發展速度差異的問題,導致CPU的速度遠遠快于內存,所以一般現在的CPU都加入了高速緩存,就是常說的解決不同硬件之間的性能差異問題。

這樣的話,很簡單的道理,加入了緩存,就必然會導致緩存一致性的問題,由此,又引入了緩存一致性協議。(如果你不知道,建議去百度一下,這里不做展開)

CPU緩存,顧名思義,越貼近CPU的緩存速度越快,容量越小,造價成本也越高,而高速緩存一般可以分為L1、L2、L3三級緩存,按照性能的劃分:L1>L2>L3。

什么是偽共享

而事實上,數據在緩存內部都是按照行來存儲的,這就叫做緩存行。緩存行一般都是2的整數冪個字節,一般來說范圍在32-256個字節之間,現在最為常見的緩存行的大小在64個字節。

所以,按照這個存儲方式,緩存中的數據并不是一個個單獨的變量的存儲方式,而是多個變量會放到一行中。

我們常說的一個例子就是數組和鏈表,數組的內存地址是連續的,當我們去讀取數組中的元素時,CPU會把數組中后續的若干個元素也加載到緩存中,以此提高效率,但是鏈表則不會,也就是說,內存地址連續的變量才有可能被放到一個緩存行中。

在多個線程并發修改一個緩存行中的多個變量時,由于只能同時有一個線程去操作緩存行,將會導致性能的下降,這個問題就稱之為偽共享。

為什么只有一個線程能去操作?我們舉個實際的栗子來說明這種情況:

假設緩存中有x,y兩個變量,他們同時已經在不同的三級緩存之中。

這時有兩個線程A和B同時去修改位于Core1和Core2的變量x和y。

如果線程A去修改Core1的緩存中的x變量,由于緩存一致性協議,Core2中對應的緩存了x變量的緩存行將會失效,他會被強制從主內存中重新去加載變量。

這樣的話,頻繁的訪問主內存,緩存基本都失效了,將會導致性能的下降,這就是偽共享的問題。

什么是偽共享

如何避免?

既然已經知道了什么是偽共享,那么怎么避免這種情況的發生?

改變行存儲的方式?想都別想了。

剩下可行的方法就是填充,如果這一行只有我這一個數據那不就好了嗎?

確實就是這樣,解決方式通常有以下兩種。

字節填充

在JDK8之前,可以通過填充字節的方式來避免偽共享的問題,如下代碼所示:

什么是偽共享

自定義填充

一般而言,緩存行有64字節,我們知道一個long是8個字節,填充5個long之后,一共就是48個字節。

而 Java 中對象頭在32位系統下占用8個字節,64位系統下占用16個字節,這樣填充5個long型即可填滿64字節,也就是一個緩存行。

@Contented注解

JDK8以及之后的版本 Java 提供了sun.misc.Contended 注解,通過@Contented注解就可以解決偽共享的問題。

什么是偽共享

注解方式

使用@Contented注解后會增加128字節的padding,并且需要開啟-XX:-RestrictContended選項后才能生效。

所以,通過以上兩種方式你會發現,對象頭大小和緩存行的大小都和操作系統位數有關,JDK的注解幫你解決了這個問題,所以推薦盡量使用注解的方式來實現。

雖然解決了偽共享問題,但是這種填充的方式也浪費了緩存資源,明明只有8B的大小,硬是使用了64B緩存空間,造成了緩存資源的浪費。

而且我們知道,緩存又小又貴,時間和空間的取舍要自己酌情考慮。

實際應用

在Java中提供了多個原子變量的操作類,就是比如AtomicLong、AtomicInteger這些,通過CAS的方式去更新變量,但是失敗會無限自旋嘗試,導致CPU資源的浪費。

為了解決高并發下的這個缺點,JDK8中新增了LongAdder類,他的使用就是對解決偽共享的實際應用。

LongAdder繼承自Striped64,內部維護了一個Cell數組,核心思想就是把單個變量的競爭拆分,多線程下如果一個Cell競爭失敗,轉而去其他Cell再次CAS重試。

什么是偽共享

Striped64成員變量

解決偽共享的真正的核心就在Cell數組,可以看到,Cell數組使用了Contented注解。

在上面我們提到數組的內存地址都是連續的,所以數組內的元素經常會被放入一個緩存行,這樣的話就會帶來偽共享的問題,影響性能。

這里使用Contented進行填充,就避免了偽共享的問題,使得數組中的元素不再共享一個緩存行。

什么是偽共享

到此,關于“什么是偽共享”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永城市| 建水县| 潢川县| 义马市| 博湖县| 尉犁县| 新兴县| 肇东市| 洪湖市| 贡觉县| 台北县| 剑河县| 张家界市| 宝坻区| 得荣县| 宁陕县| 永吉县| 乌兰察布市| 镇江市| 公主岭市| 西青区| 双峰县| 青浦区| 文安县| 湘西| 克拉玛依市| 托克逊县| 右玉县| 海南省| 休宁县| 通江县| 南康市| 三河市| 青铜峡市| 米泉市| 贵定县| 佛冈县| 武功县| 积石山| 松阳县| 遂宁市|