You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程操作bytearray时,del barr[:last_read_pos]是否线程安全?

结论:该操作完全不线程安全

Python的bytearray属于内置可变序列,它的所有修改操作(包括extend、del)都不是原子性的,读取操作在并发修改场景下也会出现异常,具体问题如下:

  • 生产者的barr.extend(data):这个操作涉及内部数组扩容、数据拷贝、长度更新等多个步骤,过程中如果有其他线程执行del或读取操作,会直接破坏数据完整性,比如写入的数据被截断、乱序,甚至触发内存错误。
  • 消费者的barr.find(...)/barr[x:y]:哪怕是读取操作,也依赖bytearray的长度和内部数据的稳定状态。如果执行读取的同时,生产者在extend或者消费者在执行del,可能出现索引越界错误,或者读到不完整、被篡改的片段(比如切片到一半时前面的内容被删掉,导致拿到错误位置的数据)。
  • del barr[:last_read_pos]的风险:这个操作会直接移动bytearray内部的剩余数据、更新长度,是典型的非原子操作。如果此时生产者正在追加数据,会导致新写入的数据被错误覆盖或丢弃;如果消费者正基于旧的last_read_pos做读取,会出现索引偏移,完全读不到正确内容,甚至触发崩溃。

正确的处理方式

必须通过线程锁来保护所有对bytearray的访问:

  1. 导入threading.Lock,创建一个全局锁对象
  2. 所有涉及barr的操作(extend、find、切片、del),都必须在with lock:代码块内执行

示例代码:

import threading

lock = threading.Lock()
barr = bytearray()

# 生产者线程
def producer(data):
    global barr
    with lock:
        barr.extend(data)

# 消费者线程
def consumer():
    global barr
    last_read_pos = 0
    while True:
        with lock:
            # 查找目标位置
            idx = barr.find(b'\x00', last_read_pos)
            if idx != -1:
                # 读取片段
                segment = barr[last_read_pos:idx]
                # 处理segment...
                last_read_pos = idx + 1
                # 清理已读数据
                del barr[:last_read_pos]

这样能保证同一时间只有一个线程在操作bytearray,彻底避免并发冲突。

内容的提问来源于stack exchange,提问作者Dinamo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:57:08