Python 2.5多线程问题,KeyError: 51,求调试帮助?

1 投票
2 回答
1318 浏览
提问于 2025-04-15 22:51

我有一个Python脚本,它会运行一个特定的脚本很多次(这是为了蒙特卡洛模拟)。我写的这个脚本是先把要运行的次数排队,然后我创建多个线程,每个线程运行一次这个脚本,完成后再继续。

当某个线程里的脚本运行完毕后,它会通过一个锁来写输出到文件里(我猜只有一个线程能在某个时间点访问这个锁)。一旦一个线程释放了锁,接下来的线程就能访问它,把自己的输出添加到之前写的文件中,并覆盖原来的内容。

当运行次数比较少,比如10次或20次时,我没有遇到问题,但当次数多了,比如50次或150次时,Python会返回一个KeyError: 51,告诉我某个元素不存在,而这个错误出现在锁的部分,这让我很困惑,因为我以为只有一个线程能同时访问锁,所以不应该出现错误。

这是我使用的类:

class errorclass(threading.Thread):

    def __init__(self, queue):
        self.__queue=queue
        threading.Thread.__init__(self)

    def run(self):
        while 1:
              item = self.__queue.get()
              if item is None: break
              result = myfunction()
              lock = threading.RLock()
              lock.acquire()
              ADD entries from current thread to entries in file and
              REWRITE FILE
              lock.release()

queue = Queue.Queue()

for i in range(threads):
    errorclass(queue).start()

for i in range(desired iterations):
    queue.put(i)
for i in range(threads):
    queue.put(None)

在进行添加/写文件操作时,Python在大量迭代时返回KeyError: 51,我在想这样使用锁是否正确,因为每个线程都有自己的锁操作,而不是每个线程都访问一个共享的锁?我该如何解决这个问题呢?

2 个回答

0

创建一个锁,然后把它传递给 errorclass.__init__,这样它们就能共享同一个实例。否则,每个线程都会把自己锁住,无法重新进入自己的关键部分,这样做其实是没什么用的。

1

你现在的情况是,每个线程在它的 run 方法中为每次 迭代 创建了一个 新锁。实际上,这样根本没有进行锁定。如果你想保护对文件的写入,就需要确保所有访问同一个文件的线程使用同一个锁对象。最简单的方法就是在全局范围内创建这个锁:

lock = threading.RLock()
class errorclass(...):
    ...
    def run(self)
        ... # get items and process
        with lock:
            ADD entries from current thread to entries in file and REWRITE FILE

在 Python 2.5 中,你需要使用 from __future__ import with_statement 来使用 with 语句,这样可以确保你不会忘记解锁,即使在发生错误的时候也不会忘记。(如果你需要兼容 Python 2.4 及更早版本,就得使用 try/finally 来处理了。)

撰写回答