【发布时间】:2012-11-07 13:09:16
【问题描述】:
因为有时它比围绕队列设计解决方案更实用,所以我想编写一个简单的包装器来使迭代器线程安全。到目前为止,我从thesetopics得到了灵感,想出了两个想法:
想法 1
class LockedIterator(object):
def __init__(self, it):
self._lock = threading.Lock()
self._it = it.__iter__()
if hasattr(self._it, 'close'):
def close(self):
with self._lock:
self._it.close()
self.__setattr__('close', close)
def __iter__(self):
return self
def next(self):
with self._lock:
return self._it.next()
我不喜欢它的是,如果我必须指定所有可能的方法,它会变得有点冗长 - 好吧,我不能 - 例如生成器的特殊情况。此外,我可能还有一些其他迭代器,它们现在已经隐藏了更具体的方法。
想法 2
class LockedIterator(object):
def __init__(self, it):
self._lock = threading.Lock()
self._it = it.__iter__()
def __getattr__(self, item):
attr = getattr(self._it, item)
if callable(attr):
def hooked(*args, **kwargs):
with self._lock:
return attr(*args, **kwargs)
setattr(self, item, hooked)
return hooked
这样更简洁,但它只能拦截调用,而不是例如直接更改属性。 (这些属性现在被隐藏以防止出现问题。)更重要的是,它使 Python 不再将我的对象识别为迭代器!
在不创建泄漏抽象的情况下,使所有迭代器(甚至更好:所有对象)都可以使用的最佳方法是什么?我不太担心不必要的锁定,但如果你能想出一个解决方案来规避这个问题,那就太好了!
【问题讨论】:
-
被迭代的东西不能在获得每一位和下一个位之间发生变异吗?
-
@GP89 我不确定你在问什么。创建锁定迭代器的全部意义在于,我可以在多个线程中安全地使用它,而无需使用队列。应该允许所有这些线程对该迭代器做任何事情,除了添加/删除属性,也许。
-
线程锁本身就是上下文管理器,因此您可以将所有 try-except-finally 代码简化为
with self._lock: -
@PaulMcGuire 谢谢!这有点清理它。
-
我不知道何时需要跨线程共享迭代器,而不是共享并发集合。整个设计让我感到不安——试图避免使用适当的队列似乎已经是一个非常容易泄漏的抽象。
标签: python iterator thread-safety python-2.7