AssertionError:组参数目前必须为None

2024-09-30 18:15:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我开始学习python和多线程。我正在试着解决这个问题。我使用类哲学家(threading.thread)。但当我放入一些示例并创建线程时,它有一个错误AssertionError:group参数现在必须为None

import threading
import time
from random import randint

exitFlag = 0

class philosophers(threading.Thread):
    
    def __int__(self, phi, hungry, eat):
        threading.Thread.__int__(self)
        #super(philosophers.self)__int__()
        self.phi = phi
        self.hungry = hungry
        self.eat = eat
        
    def hungry(self):
        time.sleep(self.hungry)
        print("Philosopher" +(self.phi) + "is hungry and want to eat" + "\n")
        startEat()
        
    def startEat(self):
        left = self.phi
        right = (self.phi+1)%5
        left.acquire()
        if right.locked():
            left.release()
        else:
            right.acquire()
        time.sleep(self.eat)
        
        right.release()
        left.release()
        print("Philosopher" +(self.phi) + "is finished" + "\n")

#def run()
thread1 = philosophers(1, 5, 3)
thread2 = philosophers(2, 4, 2)
#thread3 = philosophers(3, 6, 7)
#thread4 = philosophers(4, 2, 8)
#thread5 = philosophers(5, 3, 4)

thread1.start()
thread2.start()
#thread3.start()
#thread4.start()
#thread5.start()

thread1.join()
thread2.join()
#thread3.join()
#thread4.join()
#thread5.join()

Tags: importselfrightreleasetimedefleftstart
1条回答
网友
1楼 · 发布于 2024-09-30 18:15:08

您的主要问题是简单的打字错误:它必须是__init__而不是__int__(在两个地方)

但还有其他问题

当您执行thread.start()时,它会在系统中创建线程并执行thread.run(),所以您必须将def hungry重命名为def run

leftright是正常数int。不能将它们与acquirelockedrelease一起使用。为此需要对象threading.Lock

这并没有错,但您可以将threads保留在列表中,然后在所有threads上使用start()join()就更简单了。即使更改列表中的threads数,也不必更改这部分代码

PEP 8 Style Guide for Python Code


最后一个问题是,我不确定你的算法是否正确

至于我Philosopner可以吃(time.sleep(self.eat)),即使他没有两个叉子

在开始时left.acquire()可以给出False,但您不检查它

编辑:

我添加了更多print()以查看变量中的值以及执行代码的哪一部分,我得到:

Philosopher 4 is hungry and want to eat
Philosopher 4 left fork: True
Philosopher 4 right fork: True
Philosopher 4 is eating
Philosopher 5 is hungry and want to eat
Philosopher 2 is hungry and want to eat
Philosopher 2 left fork: True
Philosopher 2 right fork: True
Philosopher 2 is eating
Philosopher 1 is hungry and want to eat
Philosopher 1 left fork: True
Philosopher 1 doesn't have forks
Philosopher 3 is hungry and want to eat
Philosopher 2 is finished
Philosopher 3 left fork: True
Philosopher 3 doesn't have forks
Philosopher 1 is finished
Philosopher 4 is finished
Philosopher 5 left fork: True
Philosopher 5 right fork: True
Philosopher 5 is eating
Philosopher 3 is finished
Philosopher 5 is finished

还有1 doesn't have forks3 doesn't have forks但是他们不吃东西就吃完了

可能需要一些循环来尝试再次获取分叉


import threading
import time


class Philosopher(threading.Thread):  # PEP8: `UpperCaseNames` for classes.
                                      # PEP8: This class describes single Philospher so it should have name without `s` at the end
    
    def __init__(self, phi, hungry, eat, locks): #, *args, **kwargs):
        super().__init__() #*args, **kwargs)
        self.phi = phi
        self.hungry = hungry
        self.eat = eat
        self.locks = locks

    def run(self):
        time.sleep(self.hungry)
        print(f"Philosopher {self.phi} is hungry and want to eat")
        self.start_eat()  # need `self.`
        
    def start_eat(self):
        left = self.locks[self.phi-1]   # Python uses indexes `[0..4]` instead of `[1..5]`
        right = self.locks[self.phi%5]  # Python uses indexes `[0..4]` instead of `[1..5]`
        
        result = left.acquire()
        print(f"Philosopher {self.phi} left fork:", result)

        if right.locked():
            left.release()
            print(f"Philosopher {self.phi} doesn't have forks")
        else:
            result = right.acquire()            
            print(f"Philosopher {self.phi} right fork:", result)
            print(f"Philosopher {self.phi} is eating")
        time.sleep(self.eat)
        
        if right.locked():
            right.release()
        if left.locked():
            left.release()
        
        print(f"Philosopher {self.phi} is finished")


#  - main  -

# 5 locks for 5 Philosophers
locks = [threading.Lock() for _ in range(5)]

threads = [
    Philosopher(1, 5, 3, locks),
    Philosopher(2, 4, 2, locks),
    Philosopher(3, 6, 7, locks),
    Philosopher(4, 2, 8, locks),
    Philosopher(5, 3, 4, locks),
]    

for t in threads:
    t.start()

for t in threads:
    t.join()

编辑:

看来这个算法是正确的

def start_eat(self):
    left = self.locks[self.phi-1]   # Python uses indexes `[0..4]` instead of `[1..5]`
    right = self.locks[self.phi%5]  # Python uses indexes `[0..4]` instead of `[1..5]`

    while True:    
        if not left.locked():    
            result = left.acquire()
            #print(f"Philosopher {self.phi} left fork:", result)
            if right.locked():
                left.release()
                #print(f"Philosopher {self.phi} doesn't have forks")
            else:
                result = right.acquire()            
                #print(f"Philosopher {self.phi} right fork:", result)
                print(f"Philosopher {self.phi} is eating")
                time.sleep(self.eat)
                right.release()
                left.release()
                print(f"Philosopher {self.phi} is finished")
                break

结果:

Philosopher 4 is hungry and want to eat
Philosopher 4 is eating
Philosopher 5 is hungry and want to eat
Philosopher 2 is hungry and want to eat
Philosopher 2 is eating
Philosopher 1 is hungry and want to eat
Philosopher 3 is hungry and want to eat
Philosopher 2 is finished
Philosopher 1 is eating
Philosopher 1 is finished
Philosopher 4 is finished
Philosopher 5 is eating
Philosopher 3 is eating
Philosopher 5 is finished
Philosopher 3 is finished

相关问题 更多 >