关于python中死锁模拟的问题

关于python中死锁模拟的问题,python,multithreading,deadlock,Python,Multithreading,Deadlock,当我试图实现python代码来模拟死锁时,我遇到了一些有趣的问题: 1) 我使用以下代码来模拟死锁 1 from threading import * 2 import time 3 4 5 def thread_one(lock1, lock2): 6 print("thread 1 is trying to acquire lock 1") 7 lock1.acquire() 8 print("lock1 acquired by thr

当我试图实现python代码来模拟死锁时,我遇到了一些有趣的问题:

1) 我使用以下代码来模拟死锁

  1 from threading import *
  2 import time
  3
  4
  5 def thread_one(lock1, lock2):
  6     print("thread 1 is trying to acquire lock 1")
  7     lock1.acquire()
  8     print("lock1 acquired by thread 1")
  9     time.sleep(1)
 10     print("thread 1 is trying to acquire lock 2")
 11     lock2.acquire()
 12
 13
 14 def thread_two(lock1, lock2):
 15     print("thread 2 is trying to acquire lock 2")
 16     lock2.acquire()
 17     print("lock2 acquired by thread 2")
 18     time.sleep(1)
 19     print("thread 2 is trying to acquire lock 1")
 20     lock1.acquire()
 21
 22
 23 if __name__ == "__main__":
 24     lock1 = Lock()
 25     lock2 = Lock()
 26
 27     t1 = Thread(target=thread_one, args=(lock1, lock2))
 28     t2 = Thread(target=thread_two, args=(lock1, lock2))
 29
 30     t1.start()
 31     t2.start()
 32
 33     t1.join()
 34     t2.join()
以下是我的成果:

thread 1 is trying to acquire lock 1
lock1 acquired by thread 1
thread 2 is trying to acquire lock 2
lock2 acquired by thread 2
thread 1 is trying to acquire lock 2
thread 2 is trying to acquire lock 1
(program stuck here)
thread 1 is trying to acquire lock 1
lock1 acquired by thread 1
thread 2 is trying to acquire lock 2
lock2 acquired by thread 2
thread 1 is trying to release lock 2
thread 2 is trying to release lock 1
(Program completes)
如果我错了,请纠正我。我认为我的模拟是正确的,两个线程在获取第二个锁的步骤中被卡住了

2) 然后我做了以下更改:

 10     print("thread 1 is trying to release lock 2")
 11     lock2.release()

 28     t2 = Thread(target=thread_one, args=(lock1, lock2))
  5 def thread_one(lock1, lock2):
  6     print("thread 1 is trying to acquire lock 1")
  7     lock1.acquire()
  8     print("lock1 acquired by thread 1")
  9     time.sleep(1)
 10     print("thread 1 is trying to release lock 2")
 11     lock2.release()
 12
 13
 14 def thread_two(lock1, lock2):
 15     print("thread 2 is trying to acquire lock 2")
 16     lock2.acquire()
 17     print("lock2 acquired by thread 2")
 18     time.sleep(1)
 19     print("thread 2 is trying to release lock 1")
 20     lock1.release()

 27     t1 = Thread(target=thread_one, args=(lock1, lock2))
 28     t2 = Thread(target=thread_two, args=(lock1, lock2))
基本上,我希望两个线程实例都运行相同的函数thread_one,并在函数中尝试释放lock2,这还没有获得。然后我得到了这些输出:

thread 1 is trying to acquire lock 1
lock1 acquired by thread 1
thread 1 is trying to acquire lock 1
thread 1 is trying to release lock 2
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Users/bawang/.pyenv/versions/3.6.5/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/Users/bawang/.pyenv/versions/3.6.5/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "test.py", line 11, in thread_one
    lock2.release()
RuntimeError: release unlocked lock
(program stuck here)
我的问题是:为什么两个线程都挂起在那里(我需要ctrl+c两次来取消它们)?我知道第二个线程正在等待第一个线程释放锁1。但是,为什么第一个线程在抛出异常后会卡住

3) 然后,我进一步做了以下更改:

 10     print("thread 1 is trying to release lock 2")
 11     lock2.release()

 28     t2 = Thread(target=thread_one, args=(lock1, lock2))
  5 def thread_one(lock1, lock2):
  6     print("thread 1 is trying to acquire lock 1")
  7     lock1.acquire()
  8     print("lock1 acquired by thread 1")
  9     time.sleep(1)
 10     print("thread 1 is trying to release lock 2")
 11     lock2.release()
 12
 13
 14 def thread_two(lock1, lock2):
 15     print("thread 2 is trying to acquire lock 2")
 16     lock2.acquire()
 17     print("lock2 acquired by thread 2")
 18     time.sleep(1)
 19     print("thread 2 is trying to release lock 1")
 20     lock1.release()

 27     t1 = Thread(target=thread_one, args=(lock1, lock2))
 28     t2 = Thread(target=thread_two, args=(lock1, lock2))
这一次,我想看看如果锁1和锁2被一个线程获取,而在另一个线程中释放,会发生什么。以下是我的产出:

thread 1 is trying to acquire lock 1
lock1 acquired by thread 1
thread 2 is trying to acquire lock 2
lock2 acquired by thread 2
thread 1 is trying to acquire lock 2
thread 2 is trying to acquire lock 1
(program stuck here)
thread 1 is trying to acquire lock 1
lock1 acquired by thread 1
thread 2 is trying to acquire lock 2
lock2 acquired by thread 2
thread 1 is trying to release lock 2
thread 2 is trying to release lock 1
(Program completes)
我的问题是,为什么没有例外?我确实希望出现两个运行时错误:在这种情况下释放解锁锁。

1)是的。你说得对

2) 正如您所猜测的,第一个线程已经停止,但是您还有两个线程:第二个线程和主线程。第一个cntl+c终止主线程。您可以查看消息中的
keyboardinterrupt
。第一个发生在
t2.join()


3) 两个线程都已正确获取和释放。不同的线程可以获得相同的锁。因此,线程1只是释放了线程2获取的锁2,反之亦然。

没有保证代码的执行顺序,因此线程1可能会在线程2获取锁2之前释放锁2。但是您可以再次运行代码,线程2可以在线程1发布代码之前获取代码。我不确定您在中途尝试在示例中实现了什么

最后一个示例没有生成任何异常的原因应该从输出中明确:

thread 1 is trying to acquire lock 1
lock1 acquired by thread 1
thread 2 is trying to acquire lock 2
lock2 acquired by thread 2
thread 1 is trying to release lock 2
thread 2 is trying to release lock 1
线程试图做的每件事都成功了。由于您向两个线程传递了相同的锁,因此线程1没有理由无法获取锁1,然后线程2将其释放,而线程2获取锁2,然后线程1将其释放-程序可以成功完成


由于
sleep(1)
,您几乎可以保证获得该输出,尽管不是很好-如果有什么东西阻止线程2在一秒钟内启动,线程1仍可能在获得锁2之前尝试释放锁2-指望超时不是一种安全的编码方式。

1)您是正确的。2) 我不认为两个线程都被锁定了。我无法想象这在这里怎么可能。3) 锁不关心哪个线程获取并释放了它们。两个锁都已获取,并且在睡眠后都已释放。您正在将相同的锁传递给两个线程,因此它们只是获取并释放彼此的锁。感谢您的回复!现在我明白了,如果我使用RLock,我将获得3)中的预期输出。非常感谢!我把洛克和洛克的所有权搞砸了。根据python文档:Lock-->原语锁是一种同步原语,在被锁定时不属于特定线程;RLock-->获取重入锁的线程必须释放重入锁。因此,我尝试在3)中使用RLock,并获得了预期的输出:RuntimeError:cannotrelease un-acquired lock。感谢您的回答!