线程安全的排序集合

时间:2011-10-25 16:37:19

标签: python collections thread-safety sorted

Python中是否有线程安全的排序集合的实现? Python's docs参考SortedCollection但我不确定它是否是线程安全的(是吗?)
如果没有这样的实现 - 你将如何实现它?

5 个答案:

答案 0 :(得分:4)

查看代码,它似乎不是线程安全的。要从多个线程中使用它,访问它的应用程序代码应该使用信号量锁来保护。

如果你想让SortedCollection类线程安全,你可以写一个装饰器函数。

它看起来像这样:

SortedCollection:

def __init__(self):
    self.mysemaphore = threading.Semaphore()

def guard(func):
    def guarded(*args, **kwds):
        self.mysemaphore.acquire()
        try:
            return func(*args, **kwds)
        finally:
            self.mysemaphore.release()

return guarded

# edit the class, applying the decorator to its methods.
@guard
def unsafeFunc(self, a, b, c):
    ''' do work here'''

修改

不要误以为线程安全的数据结构会使您的应用程序代码线程安全。如果对SortedCollection执行多个操作,则所有这些操作都需要通过锁来保护。

即使SortedCollection是线程安全的,下面的代码也不会是:

slist.insert(1)
slist.insert(2)

另一个线程可能会在这两个语句之间插入一个项目。您需要在应用程序代码中保护。如果将其添加到应用程序代码中,则无需将SortedCollection修改为线程安全。

semaphore2.acquire()

try:
    slist.insert(1)
    slist.insert(2)
finally:
    semaphore2.release()

答案 1 :(得分:1)

Python与Java不同:如果某个类未在文档中指定其线程行为,则可以安全地假设它不是线程安全的。

Python不是用线程编写的。即便在今天,多线程确实是二等公民,因为在任何时候只有一个线程处于活动状态(这不会阻止大多数数据争用问题)。它被称为Global Interpreter Lock(GIL)。

如果没有为并发构建类或数据结构,则必须通过external lock保护对它的访问

答案 2 :(得分:1)

collections.OrderedDict 类对于更新不是线程安全的。您可以执行并发读取,但写入需要锁定。有关如何使用 OrderedDict 的锁定的示例,请参阅functools.lru_cache()的来源。

答案 3 :(得分:1)

您可以使用heapq模块维护已排序的列表。通过GIL的强大功能,所有对C Extensions的调用都是原子的(在CPython中,除非扩展显式释放锁),因此heappush和朋友都是线程安全的。

from heapq import heappush, heappop

class Heap:

    def __init__(self):
        self._heap = []

    def push(self, x):
        heappush(self._heap, x)

    def pop(self):
        return heappop(self.heap)

答案 4 :(得分:0)

原子操作在python中始终是线程安全的。如果操作不是原子操作,则只需要同步。无论线程数是多少,GIL一次只允许一次原子操作。 python中的多处理是另一回事。