如果只有一个写入器将一个字节附加到bytearray
上,并且有多个读取器从中读取数据,那么是否有可能一个或多个读取器读取的数据在扩展之前和之后都没有?
例如,如果bytearray
中的旧数据为0123
,则编写器以4567
扩展,则新数据将为01234567
。
012345
或0123abcd
之类的数据?
编辑。编写者将调用.extend(data)
或使用+= data
将数据添加到bytearray
。 data
是bytes
或另一个bytearray
对象。
答案 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类型进行操作的代码。
总而言之,如果有疑问,最好使用锁,而不必担心迭代的对象是否是本机的。