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

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

我们来看看Python的锁:

threadLock = threading.Lock()

在同步的地方,用:

threadLock.acquire()
lists.append(receiver)
threadLock.release()

进行锁的增加和释放。

锁是一种非常简单的工具,但锁的使用决定了你多线程的运行效率。

因此,我们在此介绍一种模型:读者写者模型,来解决效率的问题。

读者写者模型,简单的来说就是:有读者的时候不允许写入。

模型的概念可以看这里:http://c.biancheng.net/cpp/html/2601.html

这里我们写成Python版就行了:


class scanThread(threading.Thread):
   def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while True:
            c, addr = s.accept()
            receiver = receiveThread(c, addr)
            receiver.setDaemon(True)
            threadLock.acquire()
            lists.append(receiver)
            threadLock.release()
            receiver.start()
            print lists
            print 'Got connection from', addr
            # c.send('Thank you for connecting')

class receiveThread(threading.Thread):
    counter = 0
    
    def __init__(self, client, address):
        threading.Thread.__init__(self)
        self.client = client
        self.address = address

    def run(self):
        while True:
            try:
                msg = eval(recv_msg(self.client))
            except:
                break
            if msg:
                print msg
                if msg['type'] == 'message':
                    mutex.acquire()
                    if receiveThread.counter == 0:
                        threadLock.acquire()
                    receiveThread.counter += 1
                    mutex.release()
                    for receiver in lists:
                        if receiver.address != self.address:
                            print self.address, ' -> ', receiver.address
                            try:
                                send_msg(receiver.client, repr(msg).encode('utf8'))
                            except Exception, e:
                                lists.remove(receiver)
                    mutex.acquire()
                    receiveThread.counter -= 1
                    if receiveThread.counter == 0:
                        threadLock.release()
                    mutex.release()
                elif msg['type'] == 'command':
                    if msg['content'] == 'quit':
                        threadLock.acquire()
                        lists.remove(self)
                        threadLock.release()
                        break

完整的代码如上。

这里有一部分如send_msg函数是为了解决下一篇我们要说的TCP传输问题所封装的函数,而encode则是为了解决中文传输乱码的问题。

植入部分

如果您觉得文章不错,可以通过赞助支持我。

如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。

标签: 成品, 源码, 知识, 代码段, 语法

添加新评论