跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 求各位指点一下这里 Python lock 的用法,我想了很久还是不理解。
未分類
27 6 月 2020

求各位指点一下这里 Python lock 的用法,我想了很久还是不理解。

求各位指点一下这里 Python lock 的用法,我想了很久还是不理解。

資深大佬 : oooolongtea 7

这是一道 leetcode 题目的答案: https://leetcode.com/problems/print-foobar-alternately/discuss/603570/python3%3A-40ms-86.64-Faster-100-Less-memory-using-threading.Lock

用两个 lock 去控制 def foo()和 def bar()运行的顺序。
我不理解的地方是:
在__init__里面,self.bar_lock.acquire()已经把 self.bar_lock 给锁上了。
运行的时候,foo()和 bar()会同时进行,但是因为在 bar()里面,有一个 self.bar_lock.acquire(),这行代码之前已经运行过了,因此在这里又再一次把 self.bar_lock 给 acquire 住了,等于是 self.bar_lock 被 acquire 了两次。
我上网查了一下,遇到这个情况,第二次 acquire 的时候,如果发现这个 self.bar_lock 之前已经被 acquire,那么这个第二次的 acquire 就会停在这里,等到 self.bar_lock 被 release 。
那么我的问题来了,如果被 acquire 了两次的话,我们需要不要 release 两次? 看代码,我们不需要 release 两次。

大佬有話說 (6)

  • 資深大佬 : noqwerty

    建议读一下文档: https://docs.python.org/3/library/threading.html#threading.Lock.acquire

    另外也可以从语义上去理解,锁 (Lock) 只有上锁和解锁两种状态,不存在你说的开两次锁的情况。

  • 資深大佬 : cigarzh

    你说的那玩意是 threading.RLock()

  • 資深大佬 : js8510

    哇。leetcode 都有一千多题了呀。我还真在 在生产环境见过类似的情况。但是实现和你发的这个有不同

    作者的意图应该是这样,
    ···
    from threading import Lock

    class FooBar:
    def __init__(self, n):
    self.n = n
    self.foo_lock = Lock()
    self.bar_lock = Lock()
    self.bar_lock.acquire() # <—- 1

    def foo(self, printFoo: ‘Callable[[], None]’) -> None:
    for i in range(self.n):
    self.foo_lock.acquire() # <—- 2 | # <—- 5, blocked here and wait for foo_lock
    # printFoo() outputs “foo”. Do not change or remove this line.
    printFoo() # <—- 3
    self.bar_lock.release() # <—- 4

    def bar(self, printBar: ‘Callable[[], None]’) -> None:
    for i in range(self.n):
    self.bar_lock.acquire() # <—- 2 and blocked here and wait for bar_lock
    # printBar() outputs “bar”. Do not change or remove this line.
    printBar() # <—- 5
    self.foo_lock.release() # <—- 6
    ···

  • 資深大佬 : lpts007

    “`python
    from threading import Lock

    “`

  • 資深大佬 : gzfrankie

    因为那段代码,foo_lock 和 bar_lock 是两个不同的 lock 。
    流程:
    1. 在__INIT__里锁了 bar_lock
    2.这时候两个进程同时开始,bar 锁在 self.bar_lock.acquire()那里不动了
    3.foo 正常运行,运行结束了之后 self.bar_lock.release()解锁 bar_lock ;运行到第二次 foo_lock.acquire(),锁住不动
    4.bar_lock 被解锁,bar 继续运行,到最后解锁 foo_lock
    5.foo_lock 被解锁,foo 继续运行

    所以是两个 lock,在 foo 里解 bar_lock,在 bar 里解 foo_lock,不存在同一个 threadacquire 了两次同一个 lock 的情况

  • 資深大佬 : gzfrankie

    在看了一下你的疑问,补充一下:
    “那么我的问题来了,如果被 acquire 了两次的话,我们需要不要 release 两次? 看代码,我们不需要 release 两次。”
    不需要 release 两次,因为
    1. 如果第一次 acquire()成功,acquire()返回 True,程序运行
    2.第二次 acquire(),由于 lock 并没有被 release,程序被停在 acquire 那行;想让程序继续运行,需要在别的地方把这个 lock release 掉。
    3.release 一个已被解锁的 lock,python 会 throw RuntimeError

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具