【问题标题】:How much to lock and when锁定多少以及何时锁定
【发布时间】:2012-11-12 12:50:11
【问题描述】:

我有一个应用程序,它以给定的时间间隔循环遍历项目列表(然后这个列表的长度会有所不同),它对每个项目执行一个相当简单的操作,它不仅仅是添加一个值,也不是一些真正复杂的计算.

我想知道的是我应该像这样锁定每个项目(当前解决方案):

def method_1:
    for item in the_list:
        do_operation(item);

def do_operation(item):
    lock()
    //do some stuff.
    unlock()

或者我应该这样做:

def method_1:
    lock()
    for item in the_list:
        do_operation(item);
    unlock()

def do_operation(item):
    //do some stuff.

我想这实际上很难回答,因为我认为这在很大程度上取决于“做一些事情”是什么以及需要多长时间。老实说,我不知道这需要多少时间。特别是与 python 获取锁所需的时间相比。

如果我能以某种方式改进我的问题,请在 cmets 中告诉我。

【问题讨论】:

  • 开销往往相对较高。因此,我倾向于支持后一种选择。尤其是在这种情况下,循环中没有实质性部分不属于关键部分。另一方面,如果do_operation 在其他地方使用,并且应该始终受到保护,那么在函数内部执行锁定是有意义的。
  • 如果你不使用线程,那么没有,没有必要。您的代码中有注释建议您需要使用它。
  • 许多锁支持上下文管理器协议 (with lock: do stuff)。这在异常情况下很有帮助(替代方案是try: / finally: 子句)。

标签: python concurrency locking


【解决方案1】:

您通常希望尽可能短的锁定时间片。因此,您通常会在变量访问之前立即锁定并在之后立即将其删除。你不想阻塞一个完整的循环,因为它破坏了并发的主要原因。

在列表的情况下:您是否研究过专门用于线程执行的不同 Queue-classes

而且 jpm 的评论是当场的。如果你的其他线程也做一些事情,你也希望它们受到保护。甚至可能存在线程不足的问题。

【讨论】:

    【解决方案2】:

    我建议锁定整个列表(选项 2)。如果您只锁定每个项目,则可以在操作的中途修改列表,这可能会出现问题,具体取决于您正在做什么。每次锁定和解锁也会产生开销。

    【讨论】:

    • 这取决于您是更改列表本身,主要是长度或顺序,还是仅更改其中的元素。如果您想操作列表,您应该查看队列模块。更多情况下,您不仅仅希望多个线程来操作列表/队列的成员,因为这是并发中的基本生产者/消费者范式。
    【解决方案3】:

    如果锁只是为了保护列表(而不是项目本身),你也可以这样做

    def method_1:
        lock()
        list = the_list[:]
        unlock()
        for item in list:
            do_operation(item);
    

    【讨论】:

      猜你喜欢
      • 2017-06-15
      • 1970-01-01
      • 2021-04-16
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多