• 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()






  • 相关阅读:
    41.给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。
    Java反射学习记录
    LeetCode算法笔记-回溯法
    LeetCode算法笔记(二)
    LeetCode算法笔记(一)
    JDBC学习笔记--通用的查询方法
    JDBC学习笔记--ResultSetMetaData
    JDBC学习笔记--PreparedStatement
    Java学习笔记---字符串
    Java学习笔记---通过异常处理错误
  • 原文地址:https://www.cnblogs.com/lg04551/p/8962520.html
Copyright © 2020-2023  润新知