欢迎关注我的微信公众号:「阿拉平平」
最近写脚本时涉及到了多线程和生成器,在使用过程中遇到了数据竞争的问题,特此记录下。
在执行脚本时提示以下错误:
ValueError: generator already executing
多线程同时请求生成器数据(即同时调用next方法)就会引发该错误,所以只要在调用next方法时加个锁就可以解决。
在脚本开头处加入:
class threadsafe_iter:
"""Takes an iterator/generator and makes it thread-safe by
serializing call to the `next` method of given iterator/generator.
"""
def __init__(self, it):
self.it = it
self.lock = threading.Lock()
def __iter__(self):
return self
def __next__(self): # python3
with self.lock:
return self.it.__next__()
# def next(self): # python2
# with self.lock:
# return self.it.next()
def threadsafe_generator(f):
"""A decorator that takes a generator function and makes it thread-safe.
"""
def g(*a, **kw):
return threadsafe_iter(f(*a, **kw))
return g
说明:
- 由于next方法的不同,所以需要区别python环境。
- threadsafe_generator为装饰器,使用时只需在生成器上加入
@threadsafe_generator
即可。 - 具体的例子可以参考:https://gist.github.com/platdrag/e755f3947552804c42633a99ffd325d4