what?
进程和线程的概念:
进程是资源占用的最小单位
线程是内核调度执行的最小单位
进程和线程的主要区别:
进程之间是彼此独立的,由master进程通过fork()系统调用派生子进程
线程是共享内存空间的,主线程派生子线程
why?
进程和线程的优缺点:
进程:
优点:进程由于各自有独立的内存空间,所以更加稳定,子进程之间不受影响,但是主进程崩溃会导致全局,而且在python中不受GIL(全局解释器锁)限制,可以充分利用多核cpu
缺点:对于内存资源占用比较高,而且创建一个进程的代价比线程要大
线程:
优点:由于共享内存空间,所以资源占用比较小,并且创建的代价小于进程,在python中受到GIL的限制,导致只能使用一个cpu核心,所以某一时刻运行的线程只有一个
缺点:由于共享内存空间也导致了缺点,资源征用的问题(python中可以通过锁的机制限制),并且一个线程的崩溃可能导致整个进程崩溃
fork()系统调用:
是unix/linux上比较特殊的一个系统调用,用于创建子进程,其特殊之处在于其他的系统调用函数一般调用一次返回一次,fork()调用一个返回两次(父进程pid+子进程pid),且fork()调用时返回的子进程pid永远为0
where?(python中考虑)
多进程和多线程的共同目标是实现多任务
任务类型:cpu密集型和io密集型
cpu密集型:应该使用多进程,充分利用多核cpu实现真正意义上的并发执行
io密集型:可以使用多线程,节约资源
how?
在python中怎样使用多进程和多线程编程?
多线程
python对于多线程的支持提供了两个基础库,较为底层的thread模块和较为高层的threading模块
实现原理:
将准备并发执行的代码当做参数传递给threading.Thread()创建一个线程对象,结合程序控制结构(循环)等方式来完成此线程对象start()的多次调用,从而实现多线程
示例代码:(利用多线程实现并发socket通信服务端)
import threading ##导入线程库
import socket ##导入socket
s=socket.socket() #创建socket对象
s.bind(('0.0.0.0',8888)) #绑定套接字
s.listen(10) #监听套接字
def run(): #定义处理函数
sock,addr=s.accept()
while True:
a=sock.recv(1024)
if a:
sock.send(a.upper())
else:
sock.close()
break
if __name__ =='__main__':
for i in xrange(20): #根据for循环创建20个线程
t=threading.Thread(target=run) #创建线程对象
t.start() #运行线程
此示例的第二种写法:
import threading ##导入线程库
import socket ##导入socket
s=socket.socket() #创建socket对象
s.bind(('0.0.0.0',8888)) #绑定套接字
s.listen(10) #监听套接字
class Mythread(threading.Thread):
def run(self): #定义处理函数
sock,addr=s.accept()
while True:
a=sock.recv(1024)
if a:
sock.send(a.upper())
else:
sock.close()
break
if __name__ =='__main__':
for i in xrange(20): #根据for循环创建20个线程
t=Mythread() #创建线程对象
t.start() #运行线程
2.多进程
python提供可multiprocessing模块中的Process类来创建进程对象,同时该模块还提供了Pool类来创建进程池对象,以及Queue和Pipe实现进程间通信
实现原理:
将准备并发执行的代码当做参数传递给multiprocessing.Process()创建一个进程对象,结合程序控制结构(循环)等方式来完成此进程对象start()的多次调用,从而实现多进程
示例代码:(利用多进程实现并发socket通信服务端)
import multiprocessing ##导入线程库
import socket ##导入socket
s=socket.socket() #创建socket对象
s.bind(('0.0.0.0',8888)) #绑定套接字
s.listen(10) #监听套接字
def run(): #定义处理函数
sock,addr=s.accept()
while True:
a=sock.recv(1024)
if a:
sock.send(a.upper())
else:
sock.close()
break
if __name__ =='__main__':
for i in xrange(20): #根据for循环创建20个线程
t=multiprocess.Process(target=run) #创建线程对象
t.start() #运行线程
//可以使用ps aux | grep python 查看已经运行了20个进程
同上:也可以自定义类并继承Process类再实例化对象的方式进行编写
总结:对于多任务的情形,并发是不可避免的问题,多进程和多线程可以实现并发,但是由于其都有不可避免的缺陷,所以如何让单进程或单线程实现并发任务的处理,如nginx,就需要使用异步IO的机制,基于事件驱动,在python中实现此机制的称为协程。