并发编程
一、概念
1、非并发
程序由单个步骤序列构成
包含独立子任务的程序执行性能低
2、并发
1)异步
2)分解子任务、简化流程与逻辑
3、进程 process
一个程序的执行实例
每个进程有自己的地址空间、内存、数据栈及辅助数据
4、线程 thread
同一个进程内,可被并行激活的控制流
共享相同上下文(空间地址、数据结构)
特点:1) 便于信息共享与通信
2) 线程访问顺序差异会导致结果不一致(条件,race,condition)
5、Python GIL 全局解释器锁
Global Interpreter Lock
Python代码由虚拟机(解释器主循环)控制完成
主循环同时只能有一个控制线程执行
I/O密集型程序,建议使用多线程
计算密集型程序,建议使用多进程
二、多线程之threading模块
1、.Tread 线程类
通过基类去执行
importtimeimportthreadingdefworker(sleep_time):print('{} worker 函数开始于:{}'.format(threading.current_thread().name,time.ctime()))time.sleep(sleep_time)print('{} worker 函数结束于:{}'.format(threading.current_thread().name,time.ctime()))if__name__=='__main__':print('主函数开始于:{}'.format(time.ctime()))threads=[]t1=threading.Thread(target=worker,args=(4,))threads.append(t1)t2=threading.Thread(target=worker,args=(2,))threads.append(t2)fortinthreads:t.start()fortinthreads:t.join()print('主函数结束于:{}'.format(time.ctime()))通过派生类去执行
importtimeimportthreadingdefworker(sleep_time):print('{} worker 函数开始于:{}'.format(threading.current_thread().name,time.ctime()))time.sleep(sleep_time)print('{} worker 函数结束于:{}'.format(threading.current_thread().name,time.ctime()))classMyThread(threading.Thread):def__init__(self,func,args):threading.Thread.__init__(self)self.func=func self.args=argsdefrun(self):self.func(*self.args)if__name__=='__main__':print('主函数开始于:{}'.format(time.ctime()))threads=[]t1=MyThread(worker,(4,))threads.append(t1)t2=MyThread(worker,(2,))threads.append(t2)fortinthreads:t.start()fortinthreads:t.join()print('主函数结束于:{}'.format(time.ctime()))三、同步锁
.acquire() 获得锁
.release() 释放锁
with lock: 支持上下文操作
importtimeimportthreadingimportrandom eggs=[]lock=threading.Lock()defput_eggs(num,lst):# lock.acquire()# for i in range(1, num+1):# time.sleep(random.randint(0,2))# lst.append(i)# lock.release()withlock:foriinrange(1,num+1):time.sleep(random.randint(0,2))lst.append(i)defmain():threads=[]foriinrange(0,3):t=threading.Thread(target=put_eggs,args=(5,eggs))threads.append(t)fortinthreads:t.start()fortinthreads:t.join()if__name__=='__main__':main()print(eggs)四、队列
queue模块
importtimeimportthreadingimportrandomimportqueue q=queue.Queue()defproducer(data_queue):foriinrange(5):time.sleep(0.5)m=random.randint(1,100)data_queue.put(m)print(f'{threading.current_thread().name}往队列中添加了一个元素{m}')defconsumer(data_queue):whileTrue:try:m=data_queue.get(timeout=2)time.sleep(random.randint(0,2))print(f'{threading.current_thread().name}从队列中移除了一个元素{m}')exceptqueue.Empty:breakelse:data_queue.task_done()defmain():threads=[]p=threading.Thread(target=producer,args=(q,))p.start()time.sleep(3)foriinrange(0,2):t=threading.Thread(target=consumer,args=(q,))threads.append(t)fortinthreads:t.start()fortinthreads:t.join()if__name__=='__main__':main()Thread-1往队列中添加了一个元素47Thread-1往队列中添加了一个元素75Thread-1往队列中添加了一个元素79Thread-1往队列中添加了一个元素5Thread-1往队列中添加了一个元素16Thread-2从队列中移除了一个元素47Thread-2从队列中移除了一个元素79Thread-2从队列中移除了一个元素5Thread-3从队列中移除了一个元素75Thread-2从队列中移除了一个元素16五、多进程之multiprocessing模块
用法和threading模块一样,但是多进程可以充分利用多核多CPU的计算能力,适合计算密集型程序
六、concurrent.futures 模块
importtimeimportthreadingimportrandomimportqueueimportconcurrent.futures num_pool=list(range(1,11))defcount(n):foriinrange(10000000):i+=ireturni*ndefworker(x):res=count(x)print(f'数字{x}的计算结果是{res}')defseq_execution():start_time=time.clock()foriinnum_pool:worker(i)print(f'顺序执行的耗时是:{time.clock()-start_time}秒')defthread_execution():start_time=time.clock()withconcurrent.futures.ThreadPoolExecutor(max_workers=5)asexecutor:foriinnum_pool:executor.submit(worker,i)print(f'多线程执行的耗时是:{time.clock()-start_time}秒')defprocess_execution():start_time=time.clock()withconcurrent.futures.ProcessPoolExecutor(max_workers=5)asexecutor:foriinnum_pool:executor.submit(worker,i)print(f'多进程执行的耗时是:{time.clock()-start_time}秒')if__name__=='__main__':# seq_execution()# thread_execution()process_execution()