我有一个多线程程序(大约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()也不例外!
item=workQ.get()
socket.sendall() **# may take long time here.**
workQ.task_done()
因为sendall()可能需要很长时间,并且使用workQ的其他线程在调用task_done()==>之前无法轮流运行,所以这似乎会使整个程序处于挂起状态。