1、什么是GIL(这是Cpython解释器) GIL本质就是一把互斥锁,那既然是互斥锁,原理都一样,都是让多个并发线程同一时间只能 有一个执行 即:有了GIL的存在,同一进程内的多个线程同一时刻只能有一个在运行,意味着在Cpython中 一个进程下的多个线程无法实现并行===》意味着无法利用多核优势 但不影响并发的实现 GIL可以被比喻成执行权限,同一进程下的所以线程 要想执行都需要先抢执行权限 2、为何要有GIL 因为Cpython解释器自带垃圾回收机制不是线程安全的 3、如何用 GIL vs 自定义互斥锁 GIL相当于执行权限,会在任务无法执行的情况,被强行释放 自定义互斥锁即便是无法执行,也不会自动释放 4、有两种并发解决方案: 多进程:计算密集型 多线程:IO密集型 #计算密集型用Process进程 from multiprocessing import Process from threading import Thread import os,time def work(): res=0 for i in range(200000): res*=i if __name__ == '__main__': l=[] print(os.cpu_count())#本机为四核 start=time.time() for i in range(1,5): p=Process(target=work) l.append(p) p.start() for n in l: n.join() stop=time.time() # 进程运行时间远小于线程运行时间 print('run time is %s'%(stop-start)) IO密集型 from threading import Thread import os,time def work(): time.sleep(5) if __name__ == '__main__': start=time.time() p1=Thread(target=work) p2=Thread(target=work) p3=Thread(target=work) p4=Thread(target=work) p1.start() p2.start() p3.start() p4.start() p1.join() p2.join() p3.join() p4.join() stop=time.time() print('run time is %s'%(stop-start)) #为io密集型时,用线程效率高 定时器 from threading import Timer,current_thread def task(x): print('%s run>>>>'%x) print(current_thread().name) if __name__ == '__main__': t=Timer(3,task,args=(10,)) t.start() print('主') 会在等待3秒后执行程序 线程queue import queue 1队列:先进先出 q=queue.Queue(3) 线程队列 q.put(1) q.get() 2堆栈:先进后出 q=queue.LifoQueue() 3.优先级队列:优先级高先出来,数字越小,优先级越高 q=queue.PriorityQueue() q.put((3,'data')) q.put((-10,'data2'))元组的形式,可以为负数,优先出来 进程池与线程池 1,什么时候用池: 池的功能是限制启动的进程数或者线程数 什么时候限制: 当并发的任务数远远超过了计算机的承受能力时,即无法一次性开启过多的进程数 或者线程数时,就应该用池的概念将开启的进程数或者线程数限制在计算机 可承受的范围内 2,同步VS异步 同步、异步指的是提交任务的两种方式 同步;提交完任务后就在原地等待,直到任务运行完毕后拿到任务 的返回值,才继续运行下一行代码 异步:提交完任务(绑定一个回调函数)后根本不在原地等待,直接 运行下一行代码,等到任务有返回值后会自动触发回调函数执行 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor from threading import current_thread import os,time,random def task(n): print('%s run、、'%current_thread().name) time.sleep(5) return n**2 def parse(future): time.sleep(1) res=future.result()拿到返回值 print('%s 处理了%s'%(current_thread().name,res)) if __name__ == '__main__': pool=ThreadPoolExecutor(4)默认为核数的五倍,进程则是核数,建池 start=time.time() for i in range(1,5): future=pool.submit(task,i)异步,直接放函数及参数 future.add_done_callback(parse)#parse会在future有返回值时立刻 触发,并且将future当做参数传给parse pool.shutdown(wait=True)默认为True,关闭池入口 ,等待运行完毕 stop=time.time() print('zhu ',current_thread().name,(stop-start)) #回调函数在用并发进程时是由主进程一个一个运行 #而多线程下回调函数由线程并发运行 实现多线程并发的套接字 服务端 from socket import * from threading import Thread def talk(conn): while True: try: data=conn.recv(1024) if len(data) == 0:break conn.send(data.upper()) except ConnectionResetError: break conn.close() def server(ip,port,backlog=5): server = socket(AF_INET, SOCK_STREAM) server.bind((ip, port)) server.listen(backlog) print('starting...') while True: conn, addr = server.accept() t = Thread(target=talk, args=(conn,)) t.start() if __name__ == '__main__': server('127.0.0.1',8080) 客户端 from socket import * import os client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True: msg='%s say hello' %os.getpid() client.send(msg.encode('utf-8')) data=client.recv(1024) print(data.decode('utf-8'))
GIL 与线程池进程池
猜你喜欢
转载自blog.csdn.net/qq_35540539/article/details/81087456
今日推荐
周排行