“ bytearray”具有一个编写者和多个阅读者线程安全吗?

时间:2019-03-16 13:37:51

标签: python arrays python-3.x

如果只有一个写入器将一个字节附加到bytearray上,并且有多个读取器从中读取数据,那么是否有可能一个或多个读取器读取的数据在扩展之前和之后都没有?

例如,如果bytearray中的旧数据为0123,则编写器以4567扩展,则新数据将为01234567

扩展期间,是否有任何读者可能(由于竞争条件)读取0123450123abcd之类的数据?

编辑。编写者将调用.extend(data)或使用+= data将数据添加到bytearraydatabytes或另一个bytearray对象。

1 个答案:

答案 0 :(得分:1)

如果您只能保证一个作者,那么这取决于您要传递给bytearray.extend()方法或+=语句的可迭代类型

Python线程在字节码之间切换,并且调用bytearray.extend()或将+=语句应用于bytearray对象是单个字节码,提供的迭代不需要字节码执行。如果您传入的对象是使用Python实现的可迭代的,则所有选择都将关闭,因为这需要执行多个字节码解释步骤。

例如:

to_extend = (int(v) for v in '0123456789')
shared_bytearray_reference += to_extend  # not atomic, readers can see between 0 and 10 bytes appended

不会是原子的,因为生成器表达式循环是在Python中实现的。

但是从list对象扩展 是原子的,因为对内置类型(例如列表)的迭代是在本机代码中实现的:

to_extend = [int(v) for v in '0123456789']
shared_bytearray_reference += to_extend  # atomic, readers will see 10 bytes appended

类似地,如果您将map()迭代器与Python函数一起使用:

to_extend = map(lambda v: int(v), '0123456789')`
shared_bytearray_reference += to_extend  # not atomic, readers can see between 0 and 10 bytes appended

这不是原子的,因为每个迭代步骤都调用Python函数,并且每次都执行字节码。

但是传入一个本机函数,例如int

to_extend = map(int, '0123456789')  # int is a built-in native function
shared_bytearray_reference += to_extend  # atomic, readers will see 10 bytes appended

那么一切都可以在单个字节码解释步骤中执行。

某些本机代码将解锁全局解释器锁,从而允许其他Python线程在本机代码独立运行时执行,但几乎永远不会涉及对Python类型进行操作的代码。

总而言之,如果有疑问,最好使用锁,而不必担心迭代的对象是否是本机的。