Python
でコンビニエンス辞書を実装しようとしています - 具体的には、辞書は2つのスレッド、つまりclear
とupdate
メソッドを使用するスレッドと、その値に直接アクセスします(つまり、__getitem__
メソッドによって)。実装は以下の通りです:リーダとライタ間の安全性を確保した辞書
from threading import Lock, current_thread
class ThreadSafeDict(dict):
def __init__(self, *args, **kwargs):
self._lock = Lock()
super(ThreadSafeDict, self).__init__(*args, **kwargs)
def clear(self, *args, **kwargs):
print("thread {} acquiring clear lock".format(current_thread().ident))
self._lock.acquire()
print("thread {} acquired clear lock".format(current_thread().ident))
super(ThreadSafeDict, self).clear(*args, **kwargs)
print("thread {} releasing clear lock".format(current_thread().ident))
self._lock.release()
print("thread {} released clear lock".format(current_thread().ident))
def __getitem__(self, *args, **kwargs):
print("thread {} acquiring getitem lock".format(current_thread().ident))
self._lock.acquire()
print("thread {} acquired getitem lock".format(current_thread().ident))
val = super(ThreadSafeDict, self).__getitem__(*args, **kwargs)
print("thread {} releasing getitem lock".format(current_thread().ident))
self._lock.release()
print("thread {} released getitem lock".format(current_thread().ident))
return val
def update(self, *args, **kwargs):
print("thread {} acquiring update lock".format(current_thread().ident))
self._lock.acquire()
print("thread {} acquiring update lock".format(current_thread().ident))
super(ThreadSafeDict, self).update(*args, **kwargs)
print("thread {} releasing update lock".format(current_thread().ident))
self._lock.release()
print("thread {} released update lock".format(current_thread().ident))
私は、このスクリプトで実装をテストしています:
import threading
import random
import time
from threadsafedict import ThreadSafeDict
def reader(tsd):
while True:
try:
val = tsd[1]
except KeyError:
pass
interval = random.random()/2
time.sleep(interval)
def writer(tsd):
while True:
tsd.clear()
interval = random.random()/2
time.sleep(interval)
tsd.update({1: 'success'})
def main():
tsd = ThreadSafeDict()
w_worker = threading.Thread(target=writer, args=(tsd,))
r_worker = threading.Thread(target=reader, args=(tsd,))
w_worker.start()
r_worker.start()
w_worker.join()
r_worker.join()
if __name__ == '__main__':
main()
出力例:
thread 140536098629376 acquiring clear lock
thread 140536098629376 acquired clear lock
thread 140536098629376 releasing clear lock
thread 140536098629376 released clear lock
thread 140536090236672 acquiring getitem lock
thread 140536090236672 acquired getitem lock
thread 140536090236672 acquiring getitem lock
thread 140536098629376 acquiring update lock
私が間違って何をしているのですか?
(私はこの同時実行が既にCPython
で安全だろう実現が、私は、実装に依存しないようにしようとしている)