假设我们有一些函数,它接受一个键,从共享哈希表中检索它的值,并对它执行一些操作以获得一个新值,然后用这个新值更新哈希表。现在,该函数是多线程的,因此可能有多个线程使用相同或不同的键调用同一函数,因此需要使用互斥体进行某种竞争条件保护。我在 python 中使用锁提出了以下实现,其中我使用字典作为哈希表。 (我知道在Python中,字典操作是原子的,但这只是为了说明算法的目的)
from threading import Lock
class Solution:
def __init__(self):
self.datamap = {}
self.lockmap = {}
self.datamap_lock = Lock()
self.lockmap_lock = Lock()
def calc(self, key, param_value):
self.datamap_lock.acquire()
if key not in self.datamap:
# Create entry in hashtable if it doesnt exists
self.datamap[key] = (-sys.maxsize, 0)
self.datamap_lock.release()
self.lockmap_lock.acquire()
self.lockmap[key] = Lock()
self.lockmap_lock.release()
# Get the lock associated with this key
self.lockmap_lock.acquire()
lock = self.lockmap[key]
self.lockmap_lock.release()
lock.acquire()
self.datamap_lock.acquire()
max_, value = self.datamap[key]
self.datamap_lock.release()
# Does some operations on value to obtain a new value and put it back into the hash table
self.datamap_lock.acquire()
self.datamap[key] = (max_, value)
self.datamap_lock.release()
lock.release()
基本上,我对哈希表使用了一个互斥体,对每个键使用了一个互斥体,对从键映射到互斥体的哈希表使用了一个互斥体。这个实现是否正确且线程安全?有没有办法在不使用这么多锁/互斥锁的情况下做得更好?
def calc(self, key, param_value):
self.datamap_lock.acquire()
不,请不要这样做。
更喜欢使用 上下文管理器:
with self.datamap_lock:
...
那么你就不会忘记释放锁了。 即使发生意外的异常。