【Netty源码解读和权威指南】第83篇:Netty任务队列MpscQueue源码解析——无锁高并发的秘密

上一篇【第82篇】ChannelOutboundBuffer源码深度解析——Netty写缓冲区的秘密
下一篇【第84篇】Netty Channel注册与Selector源码解析


一、为什么不用BlockingQueue?

队列性能
LinkedBlockingQueueReentrantLock一般
MpscArrayQueue无锁(CAS)

Mpsc= Multiple Producer, Single Consumer(多生产者,单消费者)

  • EventLoop是单消费者(单线程消费)
  • 多个Handler可以提交任务(多生产者)

二、JCTools MpscQueue

// Netty使用JCTools的MpscQueue// SingleThreadEventExecutor中的任务队列Queue<Runnable>taskQueue;// PlatformDependent判断使用哪种if(PlatformDependent.hasUnsafe()){taskQueue=newMpscChunkedArrayQueue<>(maxPendingTasks);}else{taskQueue=newMpscGrowableArrayQueue<>(maxPendingTasks);}

三、CAS无锁入队

// MpscArrayQueue.offer()(简化版)// 多个生产者用CAS竞争入队位置publicbooleanoffer(Ee){longcurrentProducerIndex=lvProducerIndex();// 读volatilelongnextProducerIndex=currentProducerIndex+1;// CAS竞争下一个槽位while(!casProducerIndex(currentProducerIndex,nextProducerIndex)){currentProducerIndex=lvProducerIndex();nextProducerIndex=currentProducerIndex+1;}// 写入数据soElement(buffer,offset(nextProducerIndex),e);returntrue;}

四、单消费者批量消费

// EventLoop.runAllTasks()批量处理for(;;){Runnabletask=taskQueue.poll();// 无锁出队if(task==null)break;task.run();// 执行任务}

上一篇【第82篇】ChannelOutboundBuffer源码深度解析——Netty写缓冲区的秘密
下一篇【第84篇】Netty Channel注册与Selector源码解析