非阻塞算法是否适用于增删操作?其增删逻辑如何实现?
非阻塞算法:不止于边界场景,核心就是处理插入/删除
首先明确说:非阻塞算法完全适用于插入、删除这类核心数据操作,你看到的“无空间/无元素时返回异常或null”只是它的边界行为,绝非唯一适用场景——恰恰相反,高并发下的插入、删除才是非阻塞数据结构的主场。
先搞懂非阻塞的本质:用原子操作替代锁
非阻塞算法的核心是依赖硬件提供的原子指令(比如CAS,Compare-and-Swap),而不是传统的互斥锁。线程在执行插入、删除时,不需要抢占锁、挂起其他线程,而是通过原子操作尝试修改数据:
- 如果尝试成功,直接完成操作;
- 如果失败(说明其他线程同时在修改同一块数据),不会阻塞挂起,而是立即重试(或者根据设计返回失败)。
插入/删除的具体实现逻辑(以非阻塞队列为例)
拿常见的非阻塞链表队列(比如Java里的ConcurrentLinkedQueue)举例:
- 插入操作:
- 线程先获取当前队列的尾节点引用;
- 用CAS指令尝试把新节点设置为尾节点的
next指针; - 如果CAS成功,再用CAS把尾节点更新为新节点;
- 如果CAS失败(比如其他线程已经修改了尾节点),就重新获取尾节点,重复上述步骤——全程没有锁,线程不会被阻塞。
- 删除操作(出队):
- 获取当前头节点的引用;
- 检查头节点是否有有效元素,如果没有就跳过它(因为可能是之前的虚节点);
- 用CAS尝试把头节点的
next设置为新的头节点; - 如果CAS成功,返回原头节点的元素;失败就重试,同样不会阻塞。
关于你看到的“边界场景返回异常/null”
那些博客提到的“无空间添加元素返回失败”“无元素可消费返回null”,是非阻塞数据结构的设计选择:
- 比如非阻塞有界队列,当队列已满时,不会让插入线程阻塞等待其他线程取走元素,而是直接返回
false(或者特定异常),把“如何处理满队列”的逻辑交给调用者; - 空队列时取元素同理,直接返回
null或失败,避免线程挂起。
但这只是边界情况,非阻塞数据结构的核心能力还是在高并发下高效处理大量的插入、删除请求——毕竟如果只能处理边界场景,那它根本没存在的意义对吧?
内容的提问来源于stack exchange,提问作者anandaili
相关产品推荐
相关产品推荐

