将线程同步责任转移到共享资源中
Posted
技术标签:
【中文标题】将线程同步责任转移到共享资源中【英文标题】:moving thread-synchronisation-responisbility into shared resource 【发布时间】:2014-10-02 22:18:30 【问题描述】:给定一个由多个线程使用的对象(=实例),以下方法是最常见的(据我所知):
共享资源:
class Resource():
def return_some_value(self):
return self.somevalue
全局(或父上下文):
lock = Lock()
res = Resource()
在访问线程中:
lock.acquire()
res.return_some_value()
lock.release()
显然访问线程负责锁定和解锁共享资源。
假设共享资源更复杂,一些方法/属性是只读的,而另一些则不是。使用资源的线程现在必须知道哪个是哪个并相应地锁定。这显然容易出错,而且我有时无法选择将 Lock 对象放在何处。
现在我的问题是:是否可以将正确锁定共享资源本身的责任转移?它甚至有意义吗? 比如:
class Resource():
def __init__(self):
self.lock = Lock()
def return_some_value(self):
self.lock.acquire()
return self.somevalue
self.lock.release() # obviously this won't work
【问题讨论】:
【参考方案1】:是的,这样做非常有意义。您也可以use a Lock
as a context manager 以确保它始终发布:
class Resource():
def __init__(self):
self.lock = Lock()
def return_some_value(self):
with self.lock: # Lock gets acquired
return self.somevalue # Lock gets released
Lock
的所有者基于获取它的线程。这么多不同的调用者可以从不同的线程调用您的Resource
对象,并且锁会正常运行。
如果您需要在 Resource
上调用多个方法,这需要您一直挂在锁上,这将无法正常工作。在这种情况下,您可能需要考虑使资源本身可锁定:
class Resource():
def __init__(self):
self.lock = Lock()
def __enter__(self):
self.lock.acquire()
def __exit__(self, *args, **kwargs):
self.lock.release()
def return_some_value(self):
return self.somevalue
def some_method(self):
# stuff
def some_other_method(self):
# stuff
r = Resource()
with r:
r.some_method()
r.some_other_method()
val = r.return_some_value()
【讨论】:
谢谢。我不确定在 return 语句之后是否会释放锁。但显然,with 语句(以及 try-finally)总是如此。我不知道。 @Peter Yep, as stated in the docs: "当在 try...finally 语句的 try 套件中执行 return、break 或 continue 语句时,finally 子句也会被执行'在出去的路上'" 关于您回答的第二部分:如果这些方法彼此独立,那么两种变体都会同样有效,不是吗? @Peter 我会说如果每个方法都是独立的,那么第一个选项会更好,因为客户端根本不需要担心锁定事情。如果属性/方法对所有线程都是只读的,则无需锁定它们。唯一的例外是只读方法正在使用某些无法共享的资源(例如,从文件对象读取的方法,或使用存储在实例中的迭代器)。尽管我想您可能会争辩说这并不是真正的“只读”。以上是关于将线程同步责任转移到共享资源中的主要内容,如果未能解决你的问题,请参考以下文章