Python锁总是由同一个线程重新获取



我几天前在面试中遇到了这个问题。我真的不知道并行编程,我尝试过的显而易见的解决方案也不起作用。

问题是:写两个函数,一个打印"foo";,一次打印";条";,将在单独的线程上运行。如何确保输出始终:

foo
bar
foo
bar
...

以下是我尝试过的:

from threading import Lock, Thread

class ThreadPrinting:
def __init__(self):
self.lock = Lock()
self.count = 10
def foo(self):
for _ in range(self.count):
with self.lock:
print("foo")
def bar(self):
for _ in range(self.count):
with self.lock:
print("bar")

if __name__ == "__main__":
tp = ThreadPrinting()
t1 = Thread(target=tp.foo)
t2 = Thread(target=tp.bar)
t1.start()
t2.start()

但这只产生10〃的;foo";s,然后是10〃;条";看起来,同一个线程设法循环并在另一个线程之前重新获取锁。这里的解决方案是什么?非常感谢。

这只会产生10"foo";s,然后是10〃;条";看起来,同一个线程设法循环并在另一个线程之前重新获取锁。

这并不奇怪。以这种方式使用threading.Lock对象(也称为"互斥体"(的问题在于,与大多数编程系统中的(默认(互斥体一样,它不会试图使fair

两个线程中的任何一个在释放lock之后所做的下一件事就是,它立即尝试再次获取锁。同时,另一个线程正在休眠(也称为"阻塞"(,等待轮到它获取锁。

当对CPU时间有很大需求时,大多数操作系统的目标是最大限度地增加CPU可以做的有用工作。最好的方法是将锁授予已经在某个CPU上运行的线程,而不是浪费时间唤醒其他正在休眠的线程。

这种策略在使用锁的程序中效果很好,就像意味着要使用锁一样——也就是说,线程大部分时间都处于解锁状态,并且只有短暂地每隔一段时间就会获取一个锁,以检查或更新一些(一组(共享变量。


为了让线程轮流打印消息,您需要找到一些方法,让线程明确地对彼此说,";现在轮到你了">

请参阅我对你的问题的评论,了解你可能如何做到这一点。

@Solomon Slow提供了一个很好的解释,并为我指明了正确的方向。我最初想要一种";带值的锁";只能有条件地获得。但这并不是真的存在,并且在一个循环中忙于等待;获取锁定-检查变量-循环";不太好。相反,我用一对线程解决了这个问题。线程用来相互通信的条件对象。我相信有一个更简单的解决方案,但这是我的:

from threading import Thread, Condition

class ThreadPrinting:
def __init__(self):
self.fooCondition = Condition()
self.barCondition = Condition()
self.count = 10
def foo(self):
for _ in range(self.count):
with self.fooCondition:
self.fooCondition.wait()
print("foo")
with self.barCondition:
self.barCondition.notify()
def bar(self):
with self.fooCondition:
self.fooCondition.notify()  # Bootstrap the cycle
for _ in range(self.count):
with self.barCondition:
self.barCondition.wait()
print("bar")
with self.fooCondition:
self.fooCondition.notify()

if __name__ == "__main__":
tp = ThreadPrinting()
t1 = Thread(target=tp.foo)
t2 = Thread(target=tp.bar)
t1.start()
t2.start()

@T。Spikes对解决方案进行一点重构。

from threading import Thread, Condition

class ThreadPrinting:
def __init__(self):
self.condition = Condition()
self.count = 10
def foo(self):
for i in range(self.count):
with self.condition:
self.condition.wait()
print(f"foo")
def bar(self):
for i in range(self.count):
with self.condition:
self.condition.notify()
print(f"bar")

if __name__ == "__main__":
tp = ThreadPrinting()
t1 = Thread(target=tp.foo)
t2 = Thread(target=tp.bar)
t1.start()
t2.start()

我这样做的方式只是让第一个线程发送"foo",然后在第二个发送"bar"之前休眠1秒。两个功能在发送之间都会休眠2秒钟。这允许它们总是交替,每秒发送一个单词。

from threading import Thread
import time
def foo():
num = 0
while num < 10:
print("foo")
num = num + 1
time.sleep(2)
def bar():
num = 0
while num < 10:
print("bar")
num = num + 1
time.sleep(2)
t1 = Thread(target=foo)
t2 = Thread(target=bar)
t1.start()
time.sleep(1)
t2.start()

我尝试了100个"foo"one_answers"bar",但它仍然交替。

最新更新