Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:具有短生命周期键的线程安全字典,对吗?_Python_Multithreading_Dictionary_Thread Safety_Weak References - Fatal编程技术网

Python:具有短生命周期键的线程安全字典,对吗?

Python:具有短生命周期键的线程安全字典,对吗?,python,multithreading,dictionary,thread-safety,weak-references,Python,Multithreading,Dictionary,Thread Safety,Weak References,假设do_thing在id号可能相同或不相同的多个线程上被多次调用,例如,id为3的线程被调用4次,id不同的线程被调用一次,那么这个线程安全吗?对于特定的作业ID,一次性初始化是否会一次运行多次?PS:one_time_init保存每个ID运行一次的状态,因此如果它已经运行到完成,则调用它是不可操作的 更新代码感谢THC4k: import threading import weakref _mainlock = threading.RLock() _job_locks = weakref.W

假设do_thing在id号可能相同或不相同的多个线程上被多次调用,例如,id为3的线程被调用4次,id不同的线程被调用一次,那么这个线程安全吗?对于特定的作业ID,一次性初始化是否会一次运行多次?PS:one_time_init保存每个ID运行一次的状态,因此如果它已经运行到完成,则调用它是不可操作的

更新代码感谢THC4k:

import threading
import weakref
_mainlock = threading.RLock()
_job_locks = weakref.WeakValueDictionary()
def do_thing(job_id):
    _mainlock.acquire() #Dictionary modification lock acquire
    _job_locks.setdefault(job_id, threading.RLock()) #Possibly modifies the dictionary
    _mainlock.release()
    _job_locks[job_id].acquire()
    try:
        one_time_init(job_id)
    finally:
        _job_locks[job_id].release()
    #On function return, the weakref.WeakValueDictionary should cause the key to evaporate
看起来很安全。如果一次性初始化再次检查作业是否运行,为什么还要使用作业锁定?你可以在那里加锁。为什么RLock而不是Lock函数似乎永远不会重新进入

不管怎么说,with语句看起来更好:

import threading
import weakref
_mainlock = threading.RLock()
_job_locks = weakref.WeakValueDictionary()

def do_thing(job_id):
    with _mainlock:
        jl = _job_locks.setdefault(job_id, threading.RLock())
    with jl:
        one_time_init(job_id)
看起来很安全。如果一次性初始化再次检查作业是否运行,为什么还要使用作业锁定?你可以在那里加锁。为什么RLock而不是Lock函数似乎永远不会重新进入

不管怎么说,with语句看起来更好:

import threading
import weakref
_mainlock = threading.RLock()
_job_locks = weakref.WeakValueDictionary()

def do_thing(job_id):
    with _mainlock:
        jl = _job_locks.setdefault(job_id, threading.RLock())
    with jl:
        one_time_init(job_id)

是的,可能是我原来的设计让我看不到简单。显然,普通的锁是不会坏的。此外,我意识到在我们的示例中有一个小错误-threading.RLock将从字典中删除,因为我们没有将它存储为setdefault的返回值。我会更新主要帖子,让它看起来更像你的帖子,并接受你的答案。在Python 2.7.3和3.2.3中dict.setdefault是线程安全的之后,是否仍然需要使用mainlock?是的,可能是我最初的设计让我对简单性视而不见。显然,普通的锁是不会坏的。此外,我意识到在我们的示例中有一个小错误-threading.RLock将从字典中删除,因为我们没有将它存储为setdefault的返回值。我将更新主要帖子,使其看起来更像你的帖子,并接受你的回答。在Python 2.7.3和3.2.3中dict.setdefault被设置为线程安全后,是否仍然需要_mainlock?