CodeSky 代码之空

随手记录自己的学习过程

Python 从多人聊天室开始谈系列 - 线程同步与读者写者模型

2016-04-17 15:21分类: Python评论: 0

接下来,我们不可避免的会遇到线程同步问题,这是因为我们涉及到了共享数据的问题(也就是一个数组)。

我们来看看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)
5def 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
20def __init__(self, client, address):
21        threading.Thread.__init__(self)
22        self.client = client
23        self.address = address
24def 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)