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

相关源码:boy-learning-netty
个人博客:http://bruce.bugmakers.club
内容来自《极客时间 - Netty源码剖析与实战》

在程序开发中,我们经常用多线程技术来提高程序的工作效率,但是高并发的场景下,多线程会存在线程安全问题,用锁来解决。

内容一览:

  • 分析同步问题的核心三要素

  • 锁的分类

  • Netty 玩转锁的五个关键点

    • 在意锁的对象和范围 -> 减少粒度

    • 注意锁的对象本身大小 -> 减少空间占用

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

    • 不同场景选择不同的并发类 -> 因需而变

    • 衡量好锁的价值 -> 能不用就不用

1、分析同步问题的核心三要素

  • 原子性:“并无一气呵成,岂能无懈可击”,如:高并发下的 i++

  • 可见性:“你做的改变,别人看不见”

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

2、锁的分类

  • 竞争的态度:乐观锁(java.util.concurrent 包中的原子类) 与 悲观锁(synchronized)

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

  • 是否可共享:共享锁 与 独享锁 - ReadWriteLock,其读锁是共享锁,其写锁是独享锁

3、Netty 玩转锁的五个关键点

3.1、在意锁的对象和范围 -> 减少粒度

例:初始化 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、注意锁的对象本身大小 -> 减少空间占用

例:统计待发送的字节数 (io.netty.channel.ChannelOutboundBuffer)

AtomicLong -> Volatile long + AtomicLongFieldUpdater

AtomicLong vs long

前者是一个对象,包含对象头(object header)以用来保存 hashcode、lock等信息,32 位系统占用 8 字节,64 位系统占用 16 字节,所以在 64 位系统下:

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

至少节约 24 字节!

结论:
Atomic* objects -> Volatile primary type + static Atomic*FieldUpdater

原子类型的对象可以用 volatile 修饰的基础类型来代替,以节省空间

3.3、注意锁的速度 -> 提高速度(提高并发性)

例1:记录内存分配字节数等功能用到的 LongCounter (io.netty.util.internal.PlatformDependent#newLongCounter())

高并发时:java.util.concurrent.atomic.AtomicLong -> java.util.concurrent.atomic.LongAdder (JDK)

结论:及时衡量,使用jdk最新功能

例2:曾经根据不同情况,选择不同的并发包实现:JDK < 1.8 考虑 ConcurrentHashMapV8(ConcurrentHashMap 在 JDK8 中的版本)

3.4、不同场景选择不同的并发类 -> 因需而变

例1:关闭和等待关闭事件执行器(Event Executor):

Object.wait/notify -> CountDownLatch

io.netty.util.concurrent.SingleThreadEventExecutor#threadLock

例2:Nio Event Loop 中负责存储 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、衡量好锁的价值 -> 能不用就不用

生活场景:

饭店提供了很多包厢,服务模式:

  • 一个服务员固定服务某几个包厢模式;

  • 所有服务员服务所有的包厢模式;

表面上看,前者效率没有后者高,但实际上它避免了服务员间的沟通(上下文切换)等开销,避免客人与服务员之间导出乱串,管理简单。

局部串行:Channel 的 I/O 请求处理 Pipeline 是串行的

整体并行:多个串行化线程(Nio Event Loop)

Netty 应用场景下:局部串行 + 整体并行 > 一个队列 + 多个线程模式:

  • 降低用户开发难度、逻辑简单、提升处理性能

  • 避免锁带来的上下文切换和并发保护等额外开销

本文由博客一文多发平台 OpenWrite 发布!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 155,770评论 4 358
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,116评论 1 286
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 105,656评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,372评论 0 201
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,704评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,166评论 1 204
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,535评论 2 306
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,259评论 0 193
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,882评论 1 236
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,218评论 2 239
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,760评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,126评论 2 249
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,667评论 3 228
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,935评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,644评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,171评论 2 265
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,119评论 2 258