【发布时间】:2023-03-15 02:43:01
【问题描述】:
我知道generators are not thread safe。两个线程同时访问时,出现错误:
ValueError: 生成器已经在执行
但迭代器与生成器不同,在多线程中使用时,不会引发异常,但会有竞态条件。生成器和迭代器的比较见this article。
在那篇文章中,作者举了一个例子,一个 Counter 被两个线程同时访问,导致它的状态 'self.i' 错误更新:
class Counter:
def __init__(self):
self.i = 0
def __iter__(self):
return self
def next(self):
self.i += 1
return self.i
这样当线程停止时,self.i 不会等于两个线程更新的次数,而是更小。
但是当迭代器是列表迭代器时会出现竞争条件吗?例如:
import threading
class Counter(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.num_seen = 0
self.lock = threading.Lock()
def run(self):
global total
for x in idata:
self.num_seen += 1
print('{0} {1}'.format(self.name, self.num_seen))
with self.lock:
total += self.num_seen
count = 10000000
idata = iter([i for i in xrange(count)])
total = 0
nthreads = 5
threads = [Counter() for n in xrange(nthreads)]
for t in threads:
t.start()
for t in threads:
t.join()
print('total ' + str(total))
每次total等于count,这是否意味着迭代器是线程安全的?
【问题讨论】:
-
我也注意到objects returned by
iter()seem thread-safe。不幸的是,这不是一个记录在案的功能。 -
顺便说一句,为什么您可能需要在多个线程中使用相同的迭代器?为什么不使用明确线程安全的deque?
标签: python multithreading