python - 如何包装 Python 迭代器以使其线程安全?

标签 python iterator thread-safety python-2.7

因为有时它比围绕队列设计解决方案更实用,所以我想编写一个简单的包装器来使迭代器线程安全。到目前为止,我的灵感来自 these topics并提出了两个想法:

想法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 不再将我的对象识别为迭代器!

让所有迭代器(甚至更好:所有对象)工作的最佳方法是什么,而不创建泄漏抽象?我不太担心在不必要时锁定,但如果你能想出一个解决方案来规避它,那就太好了!

最佳答案

首先,你知道the GIL吗? ?与简单的单线程版本相比,尝试编写多线程 Python 通常会导致运行时间变慢。

您第一次尝试以线程安全方式访问迭代器似乎很合理。您可以使用生成器使其更具可读性:

def locked_iter(it):
    it = iter(it)
    lock = threading.Lock()
    while True:
        try:
            with lock:
                value = next(it)
        except StopIteration:
            return
        yield value

关于python - 如何包装 Python 迭代器以使其线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13456735/

相关文章:

C# 线程安全调用动态创建的控件

java - ReentrantLock and Condition,最佳设计

C++11 std::thread 和虚函数绑定(bind)

python - python生成器可以使用递归吗?

python - 如何根据python中的其他列将特定列值转换为一行?

c# - 了解迭代器 block 和 Dispose 方法

javascript - for循环中的jquery迭代器

python - ASP.NET MVC 上的 IronPython

python - pandas 通过非 nan 值之前和之后填充 nans

c++ - 如果不推荐使用 std::iterator ,我们还应该使用需要 std::iterator 的类或函数吗?