我有一个多线程程序(大约20个线程;有许多队列的生产者/消费者的混合体)
在其中一个线程中,它从队列弹出字符串并将其发送到远程程序
# it starts the thread like this
workQ = Queue.Queue()
stop_thr_event = threading.Event()
t = threading.Thread( target=worker, args=(stop_thr_event,) )
# in the thread's worker function
def worker(stop_event):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (myhost, int(myport))
sock.connect(server_address)
while True:
try:
item = workQ.get(timeout=1)
if print_only:
print item
else:
if item.startswith("key:"):
item = "{%s}" % item
sock.sendall(item)
workQ.task_done()
except Queue.Empty, msg:
if stop_event.isSet():
break
间歇性地,我的程序将只是挂起,没有线程做任何工作
经过反复试验,我发现我的程序只在这个线程运行时挂起
我唯一的猜测是sendall()占用了GIL,而我的整个程序都挂起了
1)这甚至是一个似是而非的理论吗?
2) 如果我的理论是正确的,我该怎么做才能使sendall()不占用GIL?让它成为无阻塞发送?在
你错了。没有网络活动保留GIL,sendall()也不例外!在
因为sendall()可能需要很长时间,而使用workQ的其他线程在调用task\u done()之前无法轮流运行。==>;这就是整个程序似乎处于挂起状态的原因。在
GIL hogging不会导致程序挂起。它可能会损害程序的性能,但这与绞刑相去甚远。很可能您正在经历某种形式的deadlock。GIL不能参与死锁,因为解释器不断地释放和重新获取GIL,获取或释放GIL通常不依赖于获取或释放任何其他资源,其他锁也不依赖于GIL。在
您对
stop_thr_event
锁的使用相当奇特。当我们把这些物体放进一系列普通的物体时,我们会把它们放进一系列的物体中。这也与经验法则有关,timeout
的唯一正确值是零和无穷大(即没有超时)。在当前的情况下,您的工作线程正在等待一秒钟,检查事件,等待一秒钟,等等,polling is a Bad Thing。在现在,如果你所说的“挂起”是指程序在恢复之前偶尔会冻结很短时间,那么就是性能不佳,所以也许GIL应该受到责备。但插座不是问题所在。问题是,您可能有大量线程在争GIL(因为它们都在尝试每秒轮询一次),如果您仍然使用2.x,那么就没有the new GIL。消除轮询将有助于解决这一问题。在
相关问题 更多 >
编程相关推荐