python - 关于python死锁模拟的问题

标签 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 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)

如有错误,请指正。我认为我的模拟是正确的,两个线程卡在获取第二个锁的步骤上。

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

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

 28     t2 = Thread(target=thread_one, 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 两次才能取消它们)?我知道第二个线程正在等待第一个线程释放lock1。但是,为什么第一个线程在抛出异常后就卡住了呢?

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

  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))

这次我想看看如果lock1&lock2被一个线程获取而在另一个线程中释放会发生什么。这些是我的输出:

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)

我的问题是为什么没有异常(exception)?在这种情况下,我确实期望出现两个RuntimeError:释放未锁定的锁

最佳答案

1) 是的。你是对的。

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

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

关于python - 关于python死锁模拟的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61313123/

相关文章:

python - Pyspark 数据框使用默认值左连接

python - 删除包含 NaN 的列

python - 我应该在 pip 的需求文件中输入什么来选择正确的 git 分支?

multithreading - 外壳程序的并行执行…带有错误代码

c# - 对并发队列的误解,单个消费者在自己的线程上从队列中工作

c++ - C++ 套接字编程中的嵌入式 Python

python - Thread._wait_for_tstate_lock() 永不返回

sql-server - SQL 服务器事件探查器 : How can I display query parameter values in deadlock graph?

python exchangelib 如何在特定日期范围内获取电子邮件?

c++ - 为什么 fclose 会挂起/死锁? ( Windows )