Python:线程+锁定大大减慢了我的应用程序

时间:2011-03-24 22:53:33

标签: python multithreading locking

假设我有一个写入文件的函数。我还有一个循环重复读取所述文件的函数。我有这两个函数在不同的线程中运行。 (实际上我正在通过MDIO读/写寄存器,这就是为什么我不能同时执行两个线程,只有一个或另一个,但为了简单起见,我们只是说它是一个文件)

现在,当我单独运行write函数时,它会很快执行。但是,当我运行线程并让它在运行之前获得锁定时,它似乎运行得非常慢。这是因为第二个线程(读取函数)轮询获取锁定?有没有办法解决这个问题?

我目前只使用一个简单的RLock,但我愿意接受任何可以提高性能的变化。

编辑:作为一个例子,我将举例说明正在发生的事情。读线程基本上总是在运行,但偶尔会有一个单独的线程调用加载。如果我通过从cmd提示符运行load来进行基准测试,那么在线程中运行的速度至少要慢3倍。

写线程:

import usbmpc # functions I made which access dll functions for hardware, etc

def load(self, lock):
    lock.acquire()
    f = open('file.txt','r')
    data = f.readlines()
    for x in data: 
        usbmpc.write(x)
    lock.release()

阅读帖子:

import usbmpc

def read(self, lock): 
    addr = START_ADDR
    while True: 
        lock.acquire()
        data = usbmpc.read(addr)
        lock.release()
        addr += 4
        if addr > BUF_SIZE: addr = START_ADDR

2 个答案:

答案 0 :(得分:4)

您是否在多核计算机上使用线程?

如果答案是肯定的,那么除非您的Python版本是3.2+,否则在运行线程应用程序时性能会下降。

David Beazly付出了相当大的努力来查找GIL在多核上发生的事情,并让我们其他人也很容易理解它。检查他的网站和那里的资源。你也许想在PyCon 2010上看到他的presentation。这是有趣的。

总而言之,在Python 3.2中,Antoine Pitrou wrote a new GIL在单机和多核机器上具有相同的性能。在以前的版本中,您拥有的内核/线程越多,性能损失就越大......

希望它有所帮助:)

答案 1 :(得分:4)

为什么不在每次写入期间获取作者的锁?您当前正在锁定加载功能的整个持续时间,读取器在加载功能完成之前永远不会进入。

其次,您应该使用上下文锁。您当前的代码不是线程安全的:

def load(lock):
    for x in data:
        with lock:
            whatever.write(x)

您的读者也一样。使用上下文来保持锁定。

第三,不要使用RLock。你知道你不需要一个,你的读/写代码不需要重新获取,所以不要给它机会,你将掩盖错误。

真正的答案在于你的问题的几条评论:GIL引起了一些争论(假设它实际上并不是你滥用锁定)。 Python threading模块很棒,GIL有时不是,但更重要的是,它产生的复杂行为被误解了。值得一提的是,主流人士认为抛出问题并不是人们所认为的灵丹妙药。它通常不是解决方案。