Python中是否有线程安全的排序集合的实现?
Python's docs参考SortedCollection但我不确定它是否是线程安全的(是吗?)
如果没有这样的实现 - 你将如何实现它?
答案 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中的多处理是另一回事。