【Netty源码解读和权威指南】第83篇:Netty任务队列MpscQueue源码解析——无锁高并发的秘密
上一篇【第82篇】ChannelOutboundBuffer源码深度解析——Netty写缓冲区的秘密
下一篇【第84篇】Netty Channel注册与Selector源码解析
一、为什么不用BlockingQueue?
| 队列 | 锁 | 性能 |
|---|---|---|
| LinkedBlockingQueue | ReentrantLock | 一般 |
| 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源码解析
