一、多进程
1.子进程永远返回0
,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()
就可以拿到父进程的ID。
2.multiprocessing
multiprocessing
模块提供了一个Process
类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束
1 import os,time,random 2 from multiprocessing import Process 3 #运行多个子进程 4 def run_child_process(name): 5 print("run child process %s(%s)"%(name,os.getpid())) 6 7 if __name__=='__main__': 8 print("parent process %s"%os.getpid()) 9 p1=Process(target=run_child_process,args=("p1",)) 10 p1.start() 11 p1.join() 12 print("child process end")
3.进程池 pool
如果要启动大量的子进程,可以用进程池的方式批量创建子进程:
1 from multiprocessing import Pool 2 import os,time,random 3 def long_time_task(name): 4 print("run task %s(%s)"%(name,os.getpid())) 5 start=time.time() 6 time.sleep(random.random()*3) 7 end=time.time() 8 print("task %s takes %0.2f seconds"%(name,(end-start))) 9 10 if __name__=='__main__': 11 print("parent process %s"%os.getpid()) 12 p=Pool(4)
#pool的默认值是cpu数 13 for i in range(5): 14 p.apply_async(long_time_task,args=(i,)) 15 print("waiting for all subprocess done") 16 p.close() 17 p.join() 18 print("all subprocess done")
执行结果:
Parent process 4984. Waiting for all subprocesses done... Run task 3 (9496)... Task 3 runs 1.65 seconds. Run task 4 (9496)... Task 4 runs 0.16 seconds. Run task 0 (11036)... Task 0 runs 2.25 seconds. Run task 2 (8680)... Task 2 runs 2.67 seconds. Run task 1 (11100)... Task 1 runs 2.97 seconds. All subprocesses done. [Finished in 3.7s]
二、多线程
多任务可以由多进程完成,也可以由一个进程内的多线程完成。
我们前面提到了进程是由若干线程组成的,一个进程至少有一个线程
1.启动线程
1 import threading,time 2 def loop(): 3 print("thread %s is running..."%threading.current_thread().name) 4 n=0 5 while n<5: 6 n=n+1 7 print("thread %s>>>%s"%(threading.current_thread().name,n)) 8 time.sleep(1) 9 print("thread %s is ended"%threading.current_thread().name) 10 print("thread %s is running"%threading.current_thread().name) 11 t=threading.Thread(target=loop,name="loopthread") 12 t.start() 13 t.join() 14 print("thread %s is ended"%threading.current_thread().name)
执行结果:
1 thread MainThread is running 2 thread loopthread is running... 3 thread loopthread>>>1 4 thread loopthread>>>2 5 thread loopthread>>>3 6 thread loopthread>>>4 7 thread loopthread>>>5 8 thread loopthread is ended 9 thread MainThread is ended 10 [Finished in 5.3s]
2.lock
多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了
1 import time,threading 2 balance=0 3 lock=threading.Lock() 4 def change_it(n): 5 global balance 6 balance=balance+n 7 balance=balance-n 8 9 def run_thread(n): 10 for i in range(100000): 11 lock.acquire() 12 try: 13 change_it(n) 14 finally: 15 lock.release() 16 t1=threading.Thread(target=run_thread,args=(5,)) 17 t2=threading.Thread(target=run_thread,args=(8,)) 18 t1.start() 19 t2.start() 20 t1.join() 21 t1.join() 22 print(balance)
三、队列
1.Process
之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing
模块包装了底层的机制,提供了Queue
、Pipes
等多种方式来交换数据。
我们以Queue
为例,在父进程中创建两个子进程,一个往Queue
里写数据,一个从Queue
里读数据:
1 from multiprocessing import Process, Queue 2 import os, time, random 3 # 写数据进程执行的代码: 4 def write(q): 5 print('Process to write: %s' % os.getpid()) 6 for value in ['A', 'B', 'C']: 7 print('Put %s to queue...' % value) 8 q.put(value) 9 time.sleep(random.random()) 10 11 # 读数据进程执行的代码: 12 def read(q): 13 print('Process to read: %s' % os.getpid()) 14 while True: 15 value = q.get(True) 16 print('Get %s from queue.' % value) 17 18 if __name__=='__main__': 19 # 父进程创建Queue,并传给各个子进程: 20 q = Queue() 21 pw = Process(target=write, args=(q,)) 22 pr = Process(target=read, args=(q,)) 23 # 启动子进程pw,写入: 24 pw.start() 25 # 启动子进程pr,读取: 26 pr.start() 27 # 等待pw结束: 28 pw.join() 29 # pr进程里是死循环,无法等待其结束,只能强行终止: 30 pr.terminate()
原文地址:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431927781401bb47ccf187b24c3b955157bb12c5882d000
https://yuedu.baidu.com/ebook/0f6a093b7dd184254b35eefdc8d376eeaeaa17e3?pn=1&rf=https%3A%2F%2Fyuedu.baidu.com%2Febook%2F0f6a093b7dd184254b35eefdc8d376eeaeaa17e3