1、学习资料:廖雪峰网站、官网文档
多进程:multiprocessing
1、multiprocessing模块是跨平台版本的多进程模块。
2、multiprocessing模块提供了一个process类来代表一个进程对象。
3、创建子进程时,只需要传入一个执行函数和函数的参数,创建一个process实例,用start()方法启动
4、join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。
5、如果要启动大量的子进程,可以用进程池(Pool)的方式批量创建子进程。
6、对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的process了。
7、子进程,很多时候子进程并不是自身,而是外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。
8、subprocess模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。
9、如果子进程还需要输入,则可以通过communicate()方式输入
10、process之间肯定是需要通信的,python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。
多线程:Threading
1、多任务可以由多进程完成,也可以由一个进程内的多线程完成。
2、进程是由若干个线程组成的,一个进程至少有一个线程。
3、高级语言通常都内置多线程的支持,python也不例外,python的线程是真正的posix thread,绝大多数情况下,使用threading这个高级模块即可。
4、启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行。
5、任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程,python的threading模块有个current_thread()函数,它永远
返回当前线程的实例。主线程实例的名字叫MainThread,子线程的名字在创建时指定,我们用LoopThread命名子线程。名字仅仅在打印时用来显示,完全没有其他意义,如果不起名字python就自动给线程命名为Thread-1,Thread-2......
6、多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给该乱了。
7、我们要确保计算正确,就要上锁,当线程因为获得了锁,因此其他线程不能同时执行了,只能等待,直到锁被释放后,获得该锁以后才能改。由于锁只有一个,无论多少线程,同一时刻最多只有一个线程持有该锁,所以,不会造成修改的冲突。创建一个锁通过threading.Lock()来实现。
8、获得锁的线程用完后一定要释放锁,否则那些苦苦等待锁的线程将永远等待下去,成为死线程。所以我们用try...finally来确保锁一定会被释放。
9、锁的好处是确保某段关键代码只能由一个线程从头到尾完整地执行,坏处是效率大大降低了。
10、多线程编程,模型复杂,容易发生冲突,必须用锁加以隔离,同时,又要小心死锁的发生。
11、python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。
进程vs线程
1、要实现多任务,通常我们会设计Master-Worker模式,Master负责分配任务,Worker负责执行任务,因此,多任务环境下,通常是一个Master,多个Worker。
2、如果用多进程实现Master-Worker,主进程就是Master,其他进程就是Worker。
3、如果用多线程实现Master-Worker,主线程就是Master,其他 线程就是Worker。
分布式进程
1、如果我们已经有一个通过Queue通信的多进程程序在同一台机器上运行,现在,由于处理任务进程任务繁重,希望把分发任务的进程和处理任务进程分布到两台机器上,怎么用分布式进程实现呢?
2、原有的Queue可以继续使用,但是,通过managers模块吧Queue通过网络暴露出去,就可以让其他机器进程访问Queue了。
3、服务进程负责启动Queue,把Queue注册到网络上,然后往Queue里面写入任务: