如何理解Netty的锁

如何理解Netty的锁,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

桦甸网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、响应式网站建设等网站项目制作,到程序开发,运营维护。创新互联于2013年创立到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联

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 应用场景下:局部串行 + 整体并行 > 一个队列 + 多个线程模式:

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

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

看完上述内容,你们掌握如何理解Netty的锁的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!

当前名称:如何理解Netty的锁
文章链接:https://www.cdcxhl.com/article26/psogcg.html

成都网站建设公司_创新互联,为您提供搜索引擎优化网站设计公司品牌网站制作品牌网站建设电子商务做网站

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

网站建设网站维护公司