多线程并不能充分利用多核处理器,如果是一个CPU计算型的任务,应该使用多进程模块 multiprocessing 。它的工作方式与线程库完全不同,但是两种库的语法却非常相似。multiprocessing给每个进程赋予单独的Python解释器,这样就规避了全局解释锁所带来的问题。
1 | from multiprocessing import Pool |
分不清楚的情况下 进行测试 一般可以先直接上多进程
进程之间的通信
进程间的通信(IPC)常用的是rpc、socket、pipe(管道)和消息队列(queue)。多进程模块中涉及到了后面3种。
- 管道pipe
1 | from multiprocessing import Process, Pipe |
- queue
1 | import time |
1 |
|
同步机制
multiprocessing的Lock、Condition、Event、RLock、Semaphore等同步原语和threading模块的机制是一样的,用法也类似,
进程之间共享状态
共享内存(value array)
服务器进程
常见的共享方式有以下几种:
Namespace。创建一个可分享的命名空间。
Value/Array。和上面共享ctypes对象的方式一样。
dict/list。创建一个可分享的dict/list,支持对应数据结构的方法。
Condition/Event/Lock/Queue/Semaphore。创建一个可分享的对应同步原语的对象。
1 | from multiprocessing import Manager, Process |
分布式进程通信
服务器端1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17from multiprocessing.managers import BaseManager
host = '127.0.0.1'
port = 9030
authkey = 'secret'
shared_list = []
class RemoteManager(BaseManager):
pass
RemoteManager.register('get_list', callable=lambda: shared_list)
mgr = RemoteManager(address=(host, port), authkey=authkey)
server = mgr.get_server()
server.serve_forever()
客户端1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19from multiprocessing.managers import BaseManager
host = '127.0.0.1'
port = 9030
authkey = 'secret'
class RemoteManager(BaseManager):
pass
RemoteManager.register('get_list')
mgr = RemoteManager(address=(host, port), authkey=authkey)
mgr.connect()
l = mgr.get_list()
print l
l.append(1)
print mgr.get_list()