Python:插座.sendall()猪吉尔?

2024-10-16 22:30:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个多线程程序(大约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?让它成为无阻塞发送?在


Tags: the程序eventif队列queuesocketitem
2条回答

你错了。没有网络活动保留GIL,sendall()也不例外!在

item=workQ.get()
socket.sendall() **# may take long time here.**
workQ.task_done() 

因为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。消除轮询将有助于解决这一问题。在

相关问题 更多 >