day31GIL、进程池与线程池、同步、异步、 阻塞、非阻塞

一、GIL:全局解释器锁

  GIL本质是就是一把互斥锁,是夹在解释器身上的,

  同一个进程内的所有线程都需要抢到GIL锁,才能执行解释器代码。

  优点:保证cpython 解释器内存管理的线程安全

  缺点:同一进程内所有的线程同一时刻只能有一个执行,也就是说cpython解释器的多线程无法实现并行

1、计算密集型应该使用多进程

# from multiprocessing import Process
# from threading import Thread
#
# import time
# # import os
# # print(os.cpu_count())
#
# def task1():
# res=0
# for i in range(1,100000000):
# res+=i
#
# def task2():
# res=0
# for i in range(1,100000000):
# res+=i
#
# def task3():
# res=0
# for i in range(1,100000000):
# res+=i
#
# def task4():
# res=0
# for i in range(1,100000000):
# res+=i
#
# if __name__ == '__main__':
# # p1=Process(target=task1)
# # p2=Process(target=task2)
# # p3=Process(target=task3)
# # p4=Process(target=task4)
#
# p1=Thread(target=task1)
# p2=Thread(target=task2)
# p3=Thread(target=task3)
# p4=Thread(target=task4)
# start_time=time.time()
# p1.start()
# p2.start()
# p3.start()
# p4.start()
# p1.join()
# p2.join()
# p3.join()
# p4.join()
# stop_time=time.time()
# print(stop_time - start_time)

2、IO密集型应该使用多线程

from multiprocessing import Process
from threading import Thread

import time


def task1():
time.sleep(3)

def task2():
time.sleep(3)

def task3():
time.sleep(3)

def task4():
time.sleep(3)

if __name__ == '__main__':
# p1=Process(target=task1)
# p2=Process(target=task2)
# p3=Process(target=task3)
# p4=Process(target=task4)

# p1=Thread(target=task1)
# p2=Thread(target=task2)
# p3=Thread(target=task3)
# p4=Thread(target=task4)
# start_time=time.time()
# p1.start()
# p2.start()
# p3.start()
# p4.start()
# p1.join()
# p2.join()
# p3.join()
# p4.join()
# stop_time=time.time()
# print(stop_time - start_time) #3.138049364089966

p_l=[]
start_time=time.time()

for i in range(500):
p=Thread(target=task1)
p_l.append(p)
p.start()

for p in p_l:
p.join()

print(time.time() - start_time)

三、线程互斥锁与GIL对比
GIL只保护解释级别的数据,不能保护线程里的数据
from threading import Thread,Lock
import time

mutex=Lock()
count=0

def task():
global count
mutex.acquire()
temp=count
time.sleep(0.1)
count=temp+1
mutex.release()



if __name__ == '__main__':
t_l=[]
for i in range(2):
t=Thread(target=task)
t_l.append(t)
t.start()
for t in t_l:
t.join()

print('主',count)


进程池VS线程池
池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务
池子内什么时候装进程:并发的任务属于计算密集型
池子内什么时候装线程:并发的任务属于IO密集型
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time,os,random
def task(X):
  print('%s 接收'%os.getpid())
  time.sleep(random.randint(2,5))
  return X**2

if __name__=='__main__':
  p=ProcessPoolExecutor()#默认开启的进程数是cpu的核数
  for i in range(20):
    p.submit(task,i)
if__name__=='__main__':
  p=ThreadPoolEx(4)#默认开启的线程数是cpu的核数*5
  for i in range(20):
    p.submit(task,i)
四、阻塞与非阻塞指的是程序的两种运行状态
阻塞:遇到IO发生阻塞,程序一旦遇到阻塞操作就会停在原地,并且立刻释放CPU资源
非阻塞(就绪或运行状态):没有遇到IO操作,或者通过某种手段让程序即便是遇到IO操作也不会停在原地,执行其他操作,力求尽可能多的占有CPU
同步与异步指的是提交任务的两种方式:
同步调用:提交完任务,就在原地等,直到任务执行完毕后,拿到返回值再执行下一行代码
异步调用:提交完任务,不在原地等,直接执行下一行代码。

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time,random

def task(X):
  print('%s'%X)
  time.sleep(random.randint(1,3))
  return X**2

if __name__=='__main__'
  #异步调用
  p=ThreadPoolExecutor(4)#默认开启的线程数是cpu的核数*5

  obj_l=[]
  for i in range(10):
    obj=p.submit(task,i)
    obj_l.append(obj)
  p.shutdown(wait=True)
  print(obj_l[2].result())
  print('主')

五基于套接字并发的通信
from socket import *
from threading import Thread
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor

tpool=ThreadPoolExecutor(3)

def communicate(conn,client_addr):
while True: # 通讯循环
try:
data = conn.recv(1024)
if not data: break
conn.send(data.upper())
except ConnectionResetError:
break
conn.close()


def server():
server=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)

while True: # 链接循环
conn,client_addr=server.accept()
print(client_addr)
# t=Thread(target=communicate,args=(conn,client_addr))
# t.start()
tpool.submit(communicate,conn,client_addr)

server.close()

if __name__ == '__main__':
server()

客户端
from socket import *

client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))

while True:
msg=input('>>>: ').strip()
if not msg:continue
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))

client.close()






猜你喜欢

转载自www.cnblogs.com/lg04551/p/8962520.html