Python 从多人聊天室开始谈系列 - 线程同步与读者写者模型
接下来,我们不可避免的会遇到线程同步问题,这是因为我们涉及到了共享数据的问题(也就是一个数组)。
我们来看看Python的锁:
1threadLock = threading.Lock()
2
在同步的地方,用:
1threadLock.acquire()
2lists.append(receiver)
3threadLock.release()
4
进行锁的增加和释放。
锁是一种非常简单的工具,但锁的使用决定了你多线程的运行效率。
因此,我们在此介绍一种模型:读者写者模型,来解决效率的问题。
读者写者模型,简单的来说就是:有读者的时候不允许写入。
模型的概念可以看这里:http://c.biancheng.net/cpp/html/2601.html
这里我们写成Python版就行了:
1
2class scanThread(threading.Thread):
3 def __init__(self):
4 threading.Thread.__init__(self)
5
def run(self):
6 while True:
7 c, addr = s.accept()
8 receiver = receiveThread(c, addr)
9 receiver.setDaemon(True)
10 threadLock.acquire()
11 lists.append(receiver)
12 threadLock.release()
13 receiver.start()
14 print lists
15 print 'Got connection from', addr
16 # c.send('Thank you for connecting')
17
18class receiveThread(threading.Thread):
19 counter = 0
20
def __init__(self, client, address):
21 threading.Thread.__init__(self)
22 self.client = client
23 self.address = address
24
def run(self):
25 while True:
26 try:
27 msg = eval(recv_msg(self.client))
28 except:
29 break
30 if msg:
31 print msg
32 if msg['type'] == 'message':
33 mutex.acquire()
34 if receiveThread.counter == 0:
35 threadLock.acquire()
36 receiveThread.counter += 1
37 mutex.release()
38 for receiver in lists:
39 if receiver.address != self.address:
40 print self.address, ' -> ', receiver.address
41 try:
42 send_msg(receiver.client, repr(msg).encode('utf8'))
43 except Exception, e:
44 lists.remove(receiver)
45 mutex.acquire()
46 receiveThread.counter -= 1
47 if receiveThread.counter == 0:
48 threadLock.release()
49 mutex.release()
50 elif msg['type'] == 'command':
51 if msg['content'] == 'quit':
52 threadLock.acquire()
53 lists.remove(self)
54 threadLock.release()
55 break
56
完整的代码如上。
这里有一部分如send_msg
函数是为了解决下一篇我们要说的TCP传输问题所封装的函数,而encode则是为了解决中文传输乱码的问题。
评论 (0)