我正在嘗試使用 python 中的互斥鎖來解決哲學家就餐問題
import threading
import time
chopstick_a = threading.Lock()
chopstick_b = threading.Lock()
chopstick_c = threading.Lock()
sushi_count = 500
def philosopher(name, first_chopstick, second_chopstick):
global sushi_count
#print(name,'is trying to eat')
while sushi_count > 0: # eat sushi until it's all gone
first_chopstick.acquire()
second_chopstick.acquire()
if sushi_count > 0:
sushi_count -= 1
print(name)
print(name, 'took a piece! Sushi remaining:', sushi_count)
second_chopstick.release()
first_chopstick.release()
if __name__ == '__main__':
threading.Thread(target=philosopher, args=('phil_one', chopstick_a, chopstick_b)).start()
threading.Thread(target=philosopher, args=('phil_two', chopstick_b, chopstick_c)).start()
threading.Thread(target=philosopher, args=('phil_three', chopstick_c, chopstick_a)).start()
問題是程式永遠不會以零結束,只有一位哲學家可以吃飯
這是一個永遠不會達到零的樣本輸出
phil_one took a piece! Sushi remaining: 466
phil_one
phil_one took a piece! Sushi remaining: 465
phil_one
phil_one took a piece! Sushi remaining: 464
phil_one
phil_one took a piece! Sushi remaining: 463
phil_one
phil_one took a piece! Sushi remaining: 462
phil_one
phil_one took a piece! Sushi remaining: 461
phil_one
phil_one took a piece! Sushi remaining: 460
phil_one
phil_one took a piece! Sushi remaining: 459
phil_one
phil_one took a piece! Sushi remaining: 458
phil_one
phil_one took a piece! Sushi remaining: 457
phil_one
phil_one took a piece! Sushi remaining: 456
uj5u.com熱心網友回復:
恭喜你,你陷入僵局。死鎖本身幾乎是一個哲學問題。發生了什么?
- 哲學家一號拿了一些壽司,放開了筷子 A 和 B。
- 哲學家二隨后獲得了筷子 B。
- 哲學家一號隨后獲得了筷子 A。
- 哲學家一號還在等著拿到筷子B,可能還需要一段時間。
uj5u.com熱心網友回復:
哲學家進餐問題是一個沒有簡單解決方案的簡單問題的示例。
在您的特定方法中,每根筷子都有一個鎖。考慮以下場景:
- 每位哲學家同時拿起左筷子。既然是開始,所有的筷子都是免費的。正是這種情況發生了。
- 每個哲學家都在等待合適的筷子。但這永遠不會發生,因為除了等待之外沒有人做任何事情。
你遇到了僵局。
現在,您可能會感到困惑,因為您實際上在掛起之前看到了一些輸出。那是因為不是每個哲學家的速度都一樣。這是一個隱喻:并非每個回圈迭代都以相同的速度作業,有些操作執行得快一點,有些操作慢一點。還有一個 OS 調度程式可以確定哪些執行緒運行以及何時運行。此外,Python 有一個叫做 GIL 的東西,這使得它幾乎是單執行緒的。所有這些(以及更多)結合起來可能導致“phil_one”哲學家回圈幾次,然后其他人運行并且整個系統最終陷入僵局。
我強烈建議您閱讀 wiki 頁面(我在開始時鏈接的那個)。你可以在那里找到一些解決問題的方法。
uj5u.com熱心網友回復:
程式永遠不會以零終止...
其他答案解決了這個問題,
...只有一位哲學家可以吃飯
這個問題被稱為饑餓:一個(或多個)執行緒不斷贏得訪問某些資源的競賽,而其他執行緒不斷輸掉競賽。
這是一種反模式,通常會導致饑餓:
while some_trivial_condition:
my_mutex.lock()
do_some_work()
my_mutex.unlock()
每次執行緒釋放my_mutex時,幾乎它所做的下一件事就是再次嘗試鎖定互斥鎖。另一個執行緒潛入那里并抓住鎖的機會視窗非常小。剛剛釋放鎖的執行緒已經在運行,而其他執行緒都處于睡眠狀態,(阻塞,)等待它,這一事實使問題變得更糟。
在大多數作業系統中,執行緒調度的目標是最有效地利用 CPU。這意味著,當兩個或多個執行緒爭用同一個資源時,作業系統將偏愛能夠最快獲取資源的執行緒,而不是等待時間最長的執行緒。
在某些編程系統中,但不是在 Python 標準庫中,有一種稱為公平鎖的東西,其行為方式完全相反:作業系統總是喚醒等待公平鎖最長時間的執行緒。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/444722.html
標籤:Python python-3.x 多线程 互斥体 餐饮哲学家
