在Python中,是否有线程安全的排序集合实现?
Python文档中提到了SortedCollection,但我不确定它是否是线程安全的(它是吗?)
如果没有这样的实现,你会如何实现它?
在Python中,是否有线程安全的排序集合实现?
Python文档中提到了SortedCollection,但我不确定它是否是线程安全的(它是吗?)
如果没有这样的实现,你会如何实现它?
浏览代码后,似乎它不是线程安全的。如果要从多个线程中使用它,则访问它的应用程序代码应该受到信号量锁的保护。
如果您想使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()
with mylock: dostuff()
。 - Jochen Ritzelmysemaphore
,你会不会错误地在不同的SortedCollection
实例之间进行锁定?你如何才能针对每个实例执行此操作? - Jonathan Livnicollections.OrderedDict类在更新时不是线程安全的。可以进行并发读取,但写入需要使用锁。有关如何在OrderedDict中使用锁的示例,请参见functools.lru_cache()源代码。
您可以使用heapq模块来维护一个排序列表。由于GIL的作用,所有对C扩展的调用都是原子性的(在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)
Python与Java不同:如果一个类在文档中没有指定其线程行为,那么可以安全地假设它不是线程安全的。
Python并非为多线程编写而设计。即使在今天,多线程也只是一个二等公民,因为一次只有一个线程处于活动状态(这并不能防止大多数数据竞争问题)。这被称为全局解释器锁(GIL)。
如果一个类或数据结构没有为并发构建,则必须通过外部锁来保护对它的访问。
在Python中,原子操作始终是线程安全的。只有当操作不是原子操作时才需要同步。无论线程数量如何,GIL始终只允许一个原子操作。但在Python中进行多进程操作则另当别论。