[英]Multithreading - Alternating between two threads using Conditions and Events in Python
我正在尝试编写一个程序,希望使用该程序在两个线程thread1和thread2之间交替。 棘手的部分是,线程应该首先开始执行的必须是thread1。 这是我到目前为止的代码:
Class Client:
#member variables
def sendFile(self,cv1,lock1):
sent=0;
while (i<self.size):
message = self.data[i:1024+i]
cv1.acquire()
BadNet.transmit(self.clientSocket,message,self.serverIP,self.serverPort)
cv1.notify()
cv1.release()
i = i+1024
sent+=1
lock1.wait()
print "File sent successfully !"
self.clientSocket.close()
def receiveAck(self,cv1,lock2):
i=0
while (1):
lock1.clear()
cv1.acquire()
cv1.wait()
print "\nentered ack !\n"
self.ack, serverAddress = self.clientSocket.recvfrom(self.buf)
cv1.release()
lock1.set()
if __name__ == "__main__":
lock1 = Event()
cv1 = Condition()
cv2= Condition()
client = Client();
client.readFile();
thread1 = Thread(target = client.sendFile, args=[cv1,lock1])
thread2 = Thread(target = client.receiveAck, args=[cv1,lock1])
thread1.start()
thread2.start()
thread1.join()
thread2.join()
我当前面临的问题是,程序最初会在两个线程之间交替(由控制台上的输出确认),但是经过任意次迭代(通常在20到80之间)后,程序只是挂起,不再执行任何迭代。
同步至少有两个问题。
首先,您使用的cv1
错误。 您的接收线程必须遍历其cv,检查条件并每次都调用wait
。 否则,您只是将简历用作损坏的事件+锁组合。 您没有这样的循环。 更重要的是,您甚至没有条件等待。
其次,您使用的lock1
错误。 您的接收线程设置事件,然后立即将其清除。 但是,不能保证发送线程已经等待。 (与前一个问题的竞赛使这个问题成为更多问题,但是即使您将其解决也仍然是一个问题。)在多核计算机上,它通常会及时到达那里,但是“通常”甚至比从来没有更糟。在线程编程中。 因此,最终在接收线程已经完成清除之后,发送线程将进入等待状态,因此它将永远等待。 同时,接收线程将等待发送线程通知,这将永远不会发生。 所以你陷入僵局。
供以后参考,在每个阻塞操作(尤其是同步操作)之前和之后添加print
语句将使调试工作变得很多:您会看到接收线程的最后一条消息是“ receivewaiting on cv1”,而发送线程的最后一条消息是“发送在lock1上等待”,这显然是死锁所在的位置。
无论如何,我不确定“无条件”修复cv或您要用作cv的事件的含义,所以我将展示如何用两个cv编写有意义的内容。 。 在这种情况下,我们最好只使用来回翻转的标志作为两个cv的条件。
在解决这个问题时,我将修复一些其他问题,这些问题使您的代码甚至无法测试(例如, i
从未初始化过),并包含调试信息,以及为使本示例完整而必须填写的内容,但否则,我将尽力保留您的结构和不相关的问题(例如Client
是老式类)。
class Client:
def __init__(self):
self.clientSocket = socket(AF_INET, SOCK_DGRAM)
self.serverIP = '127.0.0.1'
self.serverPort = 11111
self.buf = 4
self.waitack = False
def readFile(self):
self.data = ', '.join(map(str, range(100000)))
self.size = len(self.data)
#member variables
def sendFile(self,cv1,lock1):
i = 0
sent=0
while (i<self.size):
message = self.data[i:1024+i]
print "s cv1 acquire"
with cv1:
print "s sendto"
self.clientSocket.sendto(message, (self.serverIP, self.serverPort))
self.waitack = True
print "s cv1 notify"
cv1.notify()
i = i+1024
sent+=1
print "s cv2 acquire"
with cv2:
print "s cv2 wait"
while self.waitack:
cv2.wait()
print "File sent successfully !"
self.clientSocket.close()
def receiveAck(self,cv1,lock2):
i=0
while (1):
print "r cv1 acquire"
with cv1:
while not self.waitack:
print "r cv1 wait"
cv1.wait()
print "r recvfrom"
self.ack, serverAddress = self.clientSocket.recvfrom(self.buf)
i += 1
print self.ack, i
print "r cv2 acquire"
with cv2:
self.waitack = False
print "r cv2 notify"
cv2.notify()
这是一个测试服务器:
from itertools import *
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 11111))
for i in count():
data, addr = s.recvfrom(1024)
print(i)
s.sendto('ack\n', addr)
启动服务器,启动客户端,服务器将最多计数672,客户端将最多计数673(因为您的代码从1开始计数),其中包含673对平衡的消息对和“文件发送成功!”。 在末尾。 (当然,由于receiveAck
无法完成,因此客户端将永远挂起,而由于我将其编写为无限循环,则服务器将永远挂起。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.