Netty的那些“锁”事儿

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

原子性:“并无一气呵成,岂能无懈可击”

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

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

·锁的分类

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

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

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

.Netty玩转锁的五个关键点:

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

新版本的这块儿代码已经被重构了,换了别的实现方式。

但这个例子本身就你能说明问题

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

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

  • volatile long = 8 bytes
  • AtomicLong = 8 bytes (volatile long) + 16bytes(对象头)+8 bytes(引用)= 32 bytes

至少节约24字节!

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

·注意锁的速度->提高并发性

例1∶记录内存分配字节数等功能用到的LongCounter

( io.netty.util.internal.PlatformDependent#newLongCounter() )

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

结论:及时衡量、使用JDK最新的功能

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

例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

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

针对多生产者单消费者——自己实现了一个锁

MPMC——multi producermulti multi consumer

MPSC—— multi producermulti sigle consumer

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

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

整体并行:多个串行化的线程(NioEventLoop)

Netty应用场景下:

局部串行+整体并行>一个队列+多个线程模式:

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

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

避免用锁:用ThreadLocal来避免资源争用,例如Netty轻量级的线程池实现

io.netty.util.Recycler#threadLocal


__EOF__

本文作者飞飞很要强
本文链接https://www.cnblogs.com/LiPengFeiii/p/16179738.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   飞飞很要强  阅读(118)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示