【发布时间】:2011-03-18 20:14:11
【问题描述】:
我在 Cygwin 上遇到了一个奇怪的 Python 并发问题。我正在运行两个线程:
- 定期发送 UDP 数据包的线程
- 一个等待 KeyBoardInterrupt 的主线程,当它接收到一个时,它通过一个布尔标志告诉 UDP 线程停止发送
这在 Linux (python 2.6) 和 Windows (Python 2.7) 下工作得很好,但在 Cygwin 的 Python (2.6) 上存在问题。
在 Cygwin 中,套接字发送线程一直等到主线程从用户那里获得任何输入(raw_input),然后才发送它的 UDP 数据包。每次都会发生这种情况。代码如下:
import sys
import socket
import threading
from time import sleep
class UdpPacketSender(threading.Thread):
def __init__(self, address, port):
threading.Thread.__init__ (self)
self.address = (address, int(port))
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.send = True
def run(self):
while self.send:
print "Sending packet..."
self.socket.sendto("Hello", self.address)
print "sent packet"
sleep(1)
self.socket.close()
def stop_sending(self):
self.send = False
sender = UdpPacketSender("127.0.0.1", 7000)
sender.start()
try:
while True:
raw_input()
except KeyboardInterrupt:
print "Got keyboard interrupt, stopping"
sender.stop_sending()
所以在 Cygwin 下我永远不会得到打印输出“发送数据包”,直到我例如在控制台窗口上按 Enter。按下后,我得到一个“已发送数据包”,但在我再次按下某个键之前没有更多。在本机 Windows Python 和 Linux 中,我每秒都会收到“发送数据包”。
我想在 windows 中使用 Cygwin 版本进行开发,但我开始怀疑它是否真的不能正常工作。我怀疑这与 GIL 有关吗?我还尝试了一个发送标志与 threading.RLock 同步的版本,但它不会改变行为。
【问题讨论】:
-
在等待
KeyboardInterrupt时您需要raw_input()还是只需要sleep()? -
Sleep() 似乎可以解决问题。谢谢!不过有一些可疑的事情发生。如果我想要从线程 A 读取输入,并在线程 B 上执行网络 I/O 怎么办?然后问题仍然存在。这是否也意味着我不能真正通过多个线程阻塞 I/O 而不会遇到 Cygwin 上的这些锁定问题?
标签: python multithreading sockets cygwin