假设我有一个写入文件的函数。我还有一个循环重复读取所述文件的函数。我有这两个函数在不同的线程中运行。 (实际上我正在通过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
答案 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有时不是,但更重要的是,它产生的复杂行为被误解了。值得一提的是,主流人士认为抛出问题并不是人们所认为的灵丹妙药。它通常不是解决方案。