将线程同步责任转移到共享资源中

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 我会说如果每个方法都是独立的,那么第一个选项会更好,因为客户端根本不需要担心锁定事情。如果属性/方法对所有线程都是只读的,则无需锁定它们。唯一的例外是只读方法正在使用某些无法共享的资源(例如,从文件对象读取的方法,或使用存储在实例中的迭代器)。尽管我想您可能会争辩说这并不是真正的“只读”。

以上是关于将线程同步责任转移到共享资源中的主要内容,如果未能解决你的问题,请参考以下文章

线程同步

线程同步之读写锁

c ++多线程同步与不断变化的资源量

线程同步(windows平台):临界区

线程同步问题

在 C 中使用共享变量和互斥锁进行线程同步