成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

真實(shí)字節(jié)二面:什么是偽共享?

開發(fā) 前端
這個問題來自最近一個朋友字節(jié)面試碰到的,最后他也成功拿到了字節(jié)offer,這個問題我想可能挺多人不太清楚,所以想拿出來單獨(dú)說一說。

[[384235]]

這個問題來自最近一個朋友字節(jié)面試碰到的,最后他也成功拿到了字節(jié)offer,這個問題我想可能挺多人不太清楚,所以想拿出來單獨(dú)說一說。

好了,讓我們進(jìn)入正題。

什么是偽共享

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

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

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

而事實(shí)上,數(shù)據(jù)在緩存內(nèi)部都是按照行來存儲的,這就叫做緩存行。緩存行一般都是2的整數(shù)冪個字節(jié),一般來說范圍在32-256個字節(jié)之間,現(xiàn)在最為常見的緩存行的大小在64個字節(jié)。

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

我們常說的一個例子就是數(shù)組和鏈表,數(shù)組的內(nèi)存地址是連續(xù)的,當(dāng)我們?nèi)プx取數(shù)組中的元素時,CPU會把數(shù)組中后續(xù)的若干個元素也加載到緩存中,以此提高效率,但是鏈表則不會,也就是說,內(nèi)存地址連續(xù)的變量才有可能被放到一個緩存行中。

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

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

假設(shè)緩存中有x,y兩個變量,他們同時已經(jīng)在不同的三級緩存之中。

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

如果線程A去修改Core1的緩存中的x變量,由于緩存一致性協(xié)議,Core2中對應(yīng)的緩存了x變量的緩存行將會失效,他會被強(qiáng)制從主內(nèi)存中重新去加載變量。

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

如何避免?

既然已經(jīng)知道了什么是偽共享,那么怎么避免這種情況的發(fā)生?

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

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

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

字節(jié)填充

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

自定義填充

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

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

@Contented注解

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

注解方式

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

所以,通過以上兩種方式你會發(fā)現(xiàn),對象頭大小和緩存行的大小都和操作系統(tǒng)位數(shù)有關(guān),JDK的注解幫你解決了這個問題,所以推薦盡量使用注解的方式來實(shí)現(xiàn)。

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

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

實(shí)際應(yīng)用

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

為了解決高并發(fā)下的這個缺點(diǎn),JDK8中新增了LongAdder類,他的使用就是對解決偽共享的實(shí)際應(yīng)用。

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

Striped64成員變量

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

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

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

解決偽共享

好了,今天的內(nèi)容就到這里,我是艾小仙,我的slogan還沒想好,但是我們下次見。

本文轉(zhuǎn)載自微信公眾號「艾小仙」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系艾小仙公眾號。

 

責(zé)任編輯:武曉燕 來源: 艾小仙
相關(guān)推薦

2022-01-17 14:24:09

共享字節(jié)面試

2021-06-30 17:38:03

Trie 樹字符Java

2021-04-25 09:58:48

mmapJava面試

2021-03-17 15:54:32

IO零拷貝方式

2025-03-28 10:47:05

開發(fā)注解Java

2024-08-30 08:59:15

2025-04-08 09:20:00

Sentinel限流微服務(wù)

2024-04-03 09:01:34

SpringTomcat容器

2025-06-05 03:10:00

mmapmalloc共享內(nèi)存

2025-04-14 10:00:00

負(fù)載均衡Java開發(fā)

2022-09-13 14:42:35

Redis內(nèi)存函數(shù)

2024-07-30 14:01:51

Java字節(jié)碼JVM?

2024-09-29 09:50:05

2021-11-30 07:51:29

共享內(nèi)存進(jìn)程

2019-12-17 14:24:11

CPU緩存偽共享

2022-12-12 08:39:09

CPUCache偽共享

2017-07-13 16:40:16

偽共享緩存行存儲

2021-01-26 01:55:24

HTTPS網(wǎng)絡(luò)協(xié)議加密

2021-03-15 11:20:46

HTTPS優(yōu)化前端

2013-06-14 10:12:22

共享并行
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 久久午夜视频 | 日韩免费中文字幕 | 久久久久久久久99精品 | 亚洲成人综合社区 | 99re6在线| 91精品国产高清一区二区三区 | 一区二区av | 日韩一区二区免费视频 | www.成人.com | 怡红院成人在线视频 | 成人免费观看视频 | 日日夜夜精品免费视频 | 国产视频中文字幕 | 午夜激情免费视频 | 中文字幕在线观看一区 | 欧美一区精品 | 精品欧美一区二区在线观看视频 | 中文字幕一区二区三区日韩精品 | 第四色狠狠 | 欧美日韩亚洲国产 | 中文字字幕一区二区三区四区五区 | 中文字幕日韩欧美 | 午夜视频在线免费观看 | 久久亚洲一区 | 成人免费网站在线 | 狠狠插天天干 | 欧美日韩福利视频 | 日本手机在线 | 国产最新视频在线 | 久久久免费观看视频 | 91久久精品国产91久久性色tv | 亚洲精品自在在线观看 | 国产欧美在线播放 | 日韩成人精品 | 日韩精品在线看 | 色婷婷一区二区三区四区 | 麻豆国产精品777777在线 | 99亚洲综合 | 亚洲一区中文字幕 | 午夜一区二区三区在线观看 | 亚洲毛片 |