著名的Java并發(fā)編程大師都這么說了,你還不知道偽共享么欧聘!

記得關(guān)注我【看點(diǎn)代碼再上班】片林,訂閱更多好文!

全文共計(jì)2163字18圖怀骤,預(yù)計(jì)閱讀時(shí)間13分鐘

大家好费封,我是tin,這是我的第7篇原創(chuàng)文章
WechatIMG43.jpeg

圖拍攝于深圳桃園南山圖書館蒋伦,年前某個(gè)陽光明媚的周六弓摘,看到掛滿的燈籠,覺得甚是喜慶痕届。文章較長(zhǎng)韧献,先上一個(gè)目錄:上個(gè)全文目錄:

  • 一、Doug Lea

  • 二研叫、CPU緩存架構(gòu)

  • 三锤窑、CPU緩存行

  • 四、偽共享

  • 五嚷炉、結(jié)語

一渊啰、Doug lea

在微博上看到這么一句話,挺有意思的申屹。


image.png

Doug Lea是誰绘证?為什么這么說?估計(jì)還真挺多人不認(rèn)識(shí)他吧哗讥。

Doug Lea迈窟,中文名為道格·利。java.util.concurrent并發(fā)包的作者忌栅。說他是這個(gè)世界上對(duì)Java影響力最大的一個(gè)人,一點(diǎn)也不為過。因?yàn)閮纱蜫ava歷史上的大變革索绪,他都間接或直接的扮演了舉足輕重的角色湖员。2004年所推出的Tiger。Tiger廣納了15項(xiàng)JSRs的語法及標(biāo)準(zhǔn)瑞驱,其中一項(xiàng)便是JSR-166娘摔。JSR-166是來自于Doug編寫的util.concurrent包,主要是關(guān)于J.U.C的技術(shù)規(guī)范唤反。

上文摘抄自百度百科:


iShot2021-02-13 17.26.26.png

JSRs(Java Specification Requests)凳寺,表示Java規(guī)范請(qǐng)求,由JCP成員向委員會(huì)提交的Java發(fā)展議案彤侍,經(jīng)過一系列流程后肠缨,如果通過最終會(huì)體現(xiàn)在未來的Java中。

JCP全稱Java Community Process 盏阶,翻譯中文即是:Java社區(qū)進(jìn)程晒奕。JCP成立于1998年,官網(wǎng)地址https://www.jcp.org名斟,由社會(huì)各界Java組成的社區(qū)脑慧,主要規(guī)劃和領(lǐng)導(dǎo)Java的發(fā)展。

二砰盐、CPU緩存架構(gòu)

國內(nèi)另一位大神闷袒,dubbo的創(chuàng)作者,曾經(jīng)在他的ppt寫過這樣的一頁


image.png

或許有人已經(jīng)猜到這ppt作者是誰的岩梳,有興趣可自行了解(需要完整ppt也可聯(lián)系我D抑琛)。ppt描述的背后原理就是偽共享問題蒋腮。

說起偽共享淘捡,還得從cpu的緩存架構(gòu)說起。


iShot2021-02-13 13.09.12.png

CPU緩存可以分為一級(jí)緩存池摧,二級(jí)緩存焦除,三級(jí)緩存,每一級(jí)緩存中所儲(chǔ)存的全部數(shù)據(jù)都是下一級(jí)緩存的一部分作彤。當(dāng)CPU要讀取一個(gè)數(shù)據(jù)時(shí)膘魄,首先從一級(jí)緩存中查找,如果沒有找到再從二級(jí)緩存中查找竭讳,如果還是沒有就從三級(jí)緩存或內(nèi)存中查找创葡。一般來說,每級(jí)緩存的命中率大概都在80%左右绢慢,也就是說全部數(shù)據(jù)量的80%都可以在一級(jí)緩存中找到灿渴,只剩下20%的總數(shù)據(jù)量才需要從二級(jí)緩存洛波、三級(jí)緩存或內(nèi)存中讀取。

越靠近 CPU 的緩存越快也越小骚露。所以 L1 緩存很小但很快蹬挤,緊接著L2 大一些,也會(huì)慢一些棘幸,L3更慢焰扳,最后到主存,主存保存著程序運(yùn)行的所有數(shù)據(jù)误续,由所有 CPU 核共享吨悍。

三、CPU緩存行

CPU緩存由緩存行組成蹋嵌,緩存行長(zhǎng)度為64字節(jié)育瓜,可以這么認(rèn)為,緩存行是緩存更新的基本單位欣尼。緩存每次更新都從主內(nèi)存中加載連續(xù)的 64 個(gè)字節(jié)爆雹。試想,如果在內(nèi)存中有兩個(gè)緊鄰的long型變量a和b愕鼓,當(dāng)a加載到緩存時(shí)钙态,b也可以一起被加載到緩存,下一次如果訪問b則可以直接從緩存讀取菇晃,這對(duì)讀取的效率提升是非常大的册倒。


image.png

但是,正因?yàn)榫彺娑家跃彺嫘袨榛締挝惶幚砘撬停绻鹀pu core1修改a變量驻子,core1上包含a變量的緩存行將失效,同時(shí)其他core上包含a變量的緩存行也將失效估灿。此時(shí)崇呵,如果core2要訪問和a在同一緩存行上的b變量,會(huì)被告知緩存行失效馅袁,這時(shí)只能到主內(nèi)存重新加載b變量域慷。

在《Java并發(fā)編程的藝術(shù)》一書中,第二章第11頁如是說:


WechatIMG44.jpeg

Doug lea在jdk7的并發(fā)包里面新增一個(gè)隊(duì)列集合類LinkedTransferQueue汗销,它在使用volatie變量時(shí)犹褒,用一種追加字節(jié)的方式來優(yōu)化隊(duì)列出隊(duì)和入隊(duì)的性能。

四弛针、偽共享

緩存以緩存行為基本單位叠骑,當(dāng)線程修改互相獨(dú)立的變量時(shí),如果這些變量在同一緩存行中削茁,那么就會(huì)互相變量緩存值得有效性宙枷,從而影響訪問性能掉房,這就是偽共享。

看一個(gè)單元測(cè)試源碼:

package com.tin.example.falls.sharing;

import org.springframework.util.StopWatch;

/**
 * title: AutoIncrement
 * <p>
 * description: 多線程環(huán)境下慰丛,long變量自增
 *
 * @author tin @看點(diǎn)代碼再上班 on 2021/2/17 下午1:28
 */
public class AutoIncrement {

 public static void main(String[] args) throws InterruptedException {
 StopWatch stopWatch = new StopWatch("@看點(diǎn)代碼再上班");
 stopWatch.start();
 System.out.println("====== start to iterate ======");
 autoIncrement(new LongNumber());

 stopWatch.stop();
 System.out.println("cost " + stopWatch.getTotalTimeMillis() + "ms");
 }

 private static void autoIncrement(LongNumber longNumber) throws InterruptedException {
 Thread t1 = new Thread(() -> {
 for (int i = 0; i < 100000000; i++) {
 longNumber.n1++;
 }
 });

 Thread t2 = new Thread(() -> {
 for (int i = 0; i < 100000000; i++) {
 longNumber.n2++;
 }
 });

 t1.start();
 t2.start();
 t1.join();
 t2.join();
 }

 static class LongNumber {
//        @sun.misc.Contended
 volatile long n1;
 volatile long n2;
 }
}

當(dāng)我啟用兩個(gè)線程圃阳,分別自增1億次n1和n2時(shí),耗時(shí)大約3000+ms


image.png

當(dāng)我在n1字段加上注解@sun.misc.Contended璧帝,重新跑程序,耗時(shí)變?yōu)?00+ms


image.png

@sun.misc.Contended注解在Java 8后新增富寿,其用來進(jìn)行緩存行填充睬隶。它可以用于類級(jí)別的修飾,同時(shí)也可以用于字段級(jí)別的修飾页徐,當(dāng)應(yīng)用于字段級(jí)別時(shí)苏潜,被注釋的字段將和其他字段隔離開來,會(huì)被加載在獨(dú)立的緩存行上变勇。

@sun.misc.Contended注解和上文ppt中提及的追加字節(jié)效果是等同的(注解要生效需在啟動(dòng)參數(shù)上加-XX:-RestrictContended)恤左。除了加注解,如果在n1和n2中間增加16個(gè)對(duì)象引用也同樣起到作用(一個(gè)對(duì)象引用4個(gè)字節(jié))搀绣。

我們要看一個(gè)對(duì)象所占的字節(jié)數(shù)大小怎么看飞袋?分享一個(gè)好東西,引用下面的包依賴:

 <dependency>
 <groupId>org.openjdk.jol</groupId>
 <artifactId>jol-core</artifactId>
 <version>0.9</version>
 </dependency>

代碼中顯式打印對(duì)象即可:

ClassLayout.parseInstance(obj).toPrintable()

可以看到打印出來的結(jié)果:


image.png

五链患、結(jié)語

我是tin巧鸭,一個(gè)在努力讓自己變得更優(yōu)秀的普通攻城獅。自己閱歷有限麻捻、學(xué)識(shí)淺薄纲仍,如有發(fā)現(xiàn)文章不妥之處,非常歡迎加我提出贸毕,我一定細(xì)心推敲加以修改郑叠。

看到這里請(qǐng)安排個(gè)點(diǎn)贊再走吧,堅(jiān)持原創(chuàng)不容易明棍,你的正反饋是我堅(jiān)持輸出的最強(qiáng)大動(dòng)力乡革,謝謝啦!


20190911181805AMQR5B8FDFDAXGLA.gif

別忘了關(guān)注我哦署拟!???

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市歌豺,隨后出現(xiàn)的幾起案子推穷,更是在濱河造成了極大的恐慌,老刑警劉巖类咧,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馒铃,死亡現(xiàn)場(chǎng)離奇詭異蟹腾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)区宇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門娃殖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人议谷,你說我怎么就攤上這事炉爆。” “怎么了卧晓?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵芬首,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我逼裆,道長(zhǎng)郁稍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任胜宇,我火速辦了婚禮耀怜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘桐愉。我一直安慰自己财破,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布仅财。 她就那樣靜靜地躺著狈究,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盏求。 梳的紋絲不亂的頭發(fā)上抖锥,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音碎罚,去河邊找鬼磅废。 笑死,一個(gè)胖子當(dāng)著我的面吹牛荆烈,可吹牛的內(nèi)容都是我干的拯勉。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼憔购,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼宫峦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起玫鸟,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤导绷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后屎飘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妥曲,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贾费,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了檐盟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褂萧。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖葵萎,靈堂內(nèi)的尸體忽然破棺而出导犹,到底是詐尸還是另有隱情,我是刑警寧澤羡忘,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布锡足,位于F島的核電站,受9級(jí)特大地震影響壳坪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掰烟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一爽蝴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纫骑,春花似錦蝎亚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至煤墙,卻和暖如春梅惯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仿野。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來泰國打工铣减, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脚作。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓葫哗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親球涛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子劣针,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容