我有一个多线程程序(大约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()==>之前无法轮流运行,所以这似乎会使整个程序处于挂起状态。

08-25 05:44