boy-learning-netty | 11 Netty 的哪些“鎖”事

相關(guān)源碼:boy-learning-netty
個(gè)人博客:http://bruce.bugmakers.club
內(nèi)容來(lái)自《極客時(shí)間 - Netty源碼剖析與實(shí)戰(zhàn)》

在程序開(kāi)發(fā)中霞篡,我們經(jīng)常用多線程技術(shù)來(lái)提高程序的工作效率步做,但是高并發(fā)的場(chǎng)景下,多線程會(huì)存在線程安全問(wèn)題碉克,用鎖來(lái)解決靶壮。

內(nèi)容一覽:

  • 分析同步問(wèn)題的核心三要素

  • 鎖的分類

  • Netty 玩轉(zhuǎn)鎖的五個(gè)關(guān)鍵點(diǎn)

    • 在意鎖的對(duì)象和范圍 -> 減少粒度

    • 注意鎖的對(duì)象本身大小 -> 減少空間占用

    • 注意鎖的速度 -> 提高速度

    • 不同場(chǎng)景選擇不同的并發(fā)類 -> 因需而變

    • 衡量好鎖的價(jià)值 -> 能不用就不用

1窝撵、分析同步問(wèn)題的核心三要素

  • 原子性:“并無(wú)一氣呵成俺夕,豈能無(wú)懈可擊”,如:高并發(fā)下的 i++

  • 可見(jiàn)性:“你做的改變椒惨,別人看不見(jiàn)”

  • 有序性:“不按套路出牌”

2缤至、鎖的分類

  • 競(jìng)爭(zhēng)的態(tài)度:樂(lè)觀鎖(java.util.concurrent 包中的原子類) 與 悲觀鎖(synchronized)

  • 等待鎖的人是否公平:公平鎖 new ReentrantLock(true) 與 非公平鎖 new ReentrantLock()

  • 是否可共享:共享鎖 與 獨(dú)享鎖 - ReadWriteLock,其讀鎖是共享鎖康谆,其寫(xiě)鎖是獨(dú)享鎖

3凄杯、Netty 玩轉(zhuǎn)鎖的五個(gè)關(guān)鍵點(diǎn)

3.1、在意鎖的對(duì)象和范圍 -> 減少粒度

例:初始化 channel (io.netty.bootstrap.ServerBootstrap#init)

Synchronized method -> Synchronized block


    void init(Channel channel) throws Exception {
        Map<ChannelOption<?>, Object> options = this.options0();
        synchronized(options) {
            setChannelOptions(channel, options, logger);
        }

        Map<AttributeKey<?>, Object> attrs = this.attrs0();
        synchronized(attrs) {
            Iterator var5 = attrs.entrySet().iterator();

            while(true) {
                if (!var5.hasNext()) {
                    break;
                }

                Entry<AttributeKey<?>, Object> e = (Entry)var5.next();
                AttributeKey<Object> key = (AttributeKey)e.getKey();
                channel.attr(key).set(e.getValue());
            }
        }
        //...
    }

3.2秉宿、注意鎖的對(duì)象本身大小 -> 減少空間占用

例:統(tǒng)計(jì)待發(fā)送的字節(jié)數(shù) (io.netty.channel.ChannelOutboundBuffer)

AtomicLong -> Volatile long + AtomicLongFieldUpdater

AtomicLong vs long

前者是一個(gè)對(duì)象戒突,包含對(duì)象頭(object header)以用來(lái)保存 hashcode、lock等信息描睦,32 位系統(tǒng)占用 8 字節(jié)膊存,64 位系統(tǒng)占用 16 字節(jié),所以在 64 位系統(tǒng)下:

  • volatile long = 8 bytes
  • AtomicLong = 8 bytes (volatile long) + 16 bytes (object header) + 8 bytes (引用) = 32 bytes

至少節(jié)約 24 字節(jié)!

結(jié)論:
Atomic* objects -> Volatile primary type + static Atomic*FieldUpdater

原子類型的對(duì)象可以用 volatile 修飾的基礎(chǔ)類型來(lái)代替隔崎,以節(jié)省空間

3.3今艺、注意鎖的速度 -> 提高速度(提高并發(fā)性)

例1:記錄內(nèi)存分配字節(jié)數(shù)等功能用到的 LongCounter (io.netty.util.internal.PlatformDependent#newLongCounter())

高并發(fā)時(shí):java.util.concurrent.atomic.AtomicLong -> java.util.concurrent.atomic.LongAdder (JDK)

結(jié)論:及時(shí)衡量,使用jdk最新功能

例2:曾經(jīng)根據(jù)不同情況爵卒,選擇不同的并發(fā)包實(shí)現(xiàn):JDK < 1.8 考慮 ConcurrentHashMapV8(ConcurrentHashMap 在 JDK8 中的版本)

3.4虚缎、不同場(chǎng)景選擇不同的并發(fā)類 -> 因需而變

例1:關(guān)閉和等待關(guān)閉事件執(zhí)行器(Event Executor):

Object.wait/notify -> CountDownLatch

io.netty.util.concurrent.SingleThreadEventExecutor#threadLock

例2:Nio Event Loop 中負(fù)責(zé)存儲(chǔ) task 的 Queue

Jdk's LinkedBlockingQueue(MPMC) -> jctools' MPSC

MPMC: muti-producer & muti-consumer
MPSC: muti-producer & simple-consumer

io.netty.util.internal.PlatformDependent.Mpsc#newMpscQueue(int)

3.5、衡量好鎖的價(jià)值 -> 能不用就不用

生活場(chǎng)景:

飯店提供了很多包廂钓株,服務(wù)模式:

  • 一個(gè)服務(wù)員固定服務(wù)某幾個(gè)包廂模式实牡;

  • 所有服務(wù)員服務(wù)所有的包廂模式;

表面上看轴合,前者效率沒(méi)有后者高创坞,但實(shí)際上它避免了服務(wù)員間的溝通(上下文切換)等開(kāi)銷,避免客人與服務(wù)員之間導(dǎo)出亂串受葛,管理簡(jiǎn)單题涨。

局部串行:Channel 的 I/O 請(qǐng)求處理 Pipeline 是串行的

整體并行:多個(gè)串行化線程(Nio Event Loop)

Netty 應(yīng)用場(chǎng)景下:局部串行 + 整體并行 > 一個(gè)隊(duì)列 + 多個(gè)線程模式:

  • 降低用戶開(kāi)發(fā)難度、邏輯簡(jiǎn)單总滩、提升處理性能

  • 避免鎖帶來(lái)的上下文切換和并發(fā)保護(hù)等額外開(kāi)銷

本文由博客一文多發(fā)平臺(tái) OpenWrite 發(fā)布纲堵!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市闰渔,隨后出現(xiàn)的幾起案子席函,更是在濱河造成了極大的恐慌,老刑警劉巖澜建,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蝌以,居然都是意外死亡炕舵,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門跟畅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咽筋,“玉大人,你說(shuō)我怎么就攤上這事徊件〖楣ィ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵虱痕,是天一觀的道長(zhǎng)睹耐。 經(jīng)常有香客問(wèn)我,道長(zhǎng)部翘,這世上最難降的妖魔是什么硝训? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上窖梁,老公的妹妹穿的比我還像新娘赘风。我一直安慰自己,他們只是感情好纵刘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布邀窃。 她就那樣靜靜地躺著,像睡著了一般假哎。 火紅的嫁衣襯著肌膚如雪瞬捕。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天位谋,我揣著相機(jī)與錄音山析,去河邊找鬼。 笑死掏父,一個(gè)胖子當(dāng)著我的面吹牛笋轨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赊淑,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼爵政,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了陶缺?” 一聲冷哼從身側(cè)響起钾挟,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饱岸,沒(méi)想到半個(gè)月后掺出,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苫费,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年汤锨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片百框。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闲礼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铐维,到底是詐尸還是另有隱情柬泽,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布嫁蛇,位于F島的核電站锨并,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏睬棚。R本人自食惡果不足惜琳疏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一有决、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧空盼,春花似錦书幕、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至篱瞎,卻和暖如春苟呐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俐筋。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工牵素, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人澄者。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓笆呆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親粱挡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赠幕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355