亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池

系統 1603 0

目錄

  • Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池
    • 1.昨日回顧
    • 2.死鎖現象與遞歸鎖
      • 2.1死鎖現象
      • 2.2遞歸鎖
    • 3.信號量
    • 4.GIL全局解釋器鎖
      • 4.1背景
      • 4.2為什么加鎖
    • 5.GIL與Lock鎖的區別
    • 6.驗證計算密集型IO密集型的效率
      • 6.1 IO密集型
      • 6.2 計算密集型
    • 7.多線程實現socket通信
      • 7.1服務端
      • 7.2客戶端
    • 8.進程池,線程池

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池

1.昨日回顧

          
            #生產者消費者模型.
#    生產者: 產生數據,
#    消費者: 接收數據并做下一步處理
#    容器: 隊列.
#進程, 線程:
#   進程就是資源單位,線程就是執行單位.
#進程與線程的區別:
#   線程: 開銷小,速度快,同一個進程下的線程資源內存級別共享.
#   進程: 開銷巨大,速度慢, 不同進程的數據內存級別不共享.
#join: 阻塞,
#   t1.join()  阻塞.
#   print('主')
#getname, setname  .name
#activeCount() 線程的數量
守護線程: 如果守護線程的生命周期小于其他線程,則他肯定先結束,否則等待其他非守護線程和主線程結束之后結束.

#互斥鎖,鎖
          
        

2.死鎖現象與遞歸鎖

          
            #遞歸鎖可以解決死鎖現象,業務需要多個鎖時,先要考慮遞歸鎖
          
        

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池_第1張圖片

2.1死鎖現象

          
            # from threading import Thread
# from threading import Lock
# import time
#
# lock_A = Lock()
# lock_B = Lock()
#
#
# class MyThread(Thread):
#
#     def run(self):
#         self.f1()
#         self.f2()
#
#
#     def f1(self):
#
#         lock_A.acquire()
#         print(f'{self.name}拿到了A鎖')
#
#         lock_B.acquire()
#         print(f'{self.name}拿到了B鎖')
#
#         lock_B.release()
#
#         lock_A.release()
#
#     def f2(self):
#
#         lock_B.acquire()
#         print(f'{self.name}拿到了B鎖')
#
#         time.sleep(0.1)
#         lock_A.acquire()
#         print(f'{self.name}拿到了A鎖')
#
#         lock_A.release()
#         lock_B.release()
#
# if __name__ == '__main__':
#
#     for i in range(3):
#         t = MyThread()
#         t.start()
          
        

2.2遞歸鎖

          
            遞歸鎖有一個計數的功能, 原數字為0,上一次鎖,計數+1,釋放一次鎖,計數-1,
只要遞歸鎖上面的數字不為零,其他線程就不能搶鎖.

# from threading import Thread
# from threading import RLock
# import time
#
# lock_A = lock_B = RLock()

# 遞歸鎖有一個計數的功能, 原數字為0,上一次鎖,計數+1,釋放一次鎖,計數-1,
# 只要遞歸鎖上面的數字不為零,其他線程就不能搶鎖.
# class MyThread(Thread):
#
#     def run(self):
#         self.f1()
#         self.f2()
#
#
#     def f1(self):
#
#         lock_A.acquire()
#         print(f'{self.name}拿到了A鎖')
#
#         lock_B.acquire()
#         print(f'{self.name}拿到了B鎖')
#
#         lock_B.release()
#
#         lock_A.release()
#
#     def f2(self):
#
#         lock_B.acquire()
#         print(f'{self.name}拿到了B鎖')
#
#         time.sleep(0.1)
#         lock_A.acquire()
#         print(f'{self.name}拿到了A鎖')
#
#         lock_A.release()
#
#         lock_B.release()
#
# if __name__ == '__main__':
#
#     for i in range(3):
#         t = MyThread()
#         t.start()
          
        

3.信號量

          
            也是一種鎖,控制并發數量

# from threading import Thread, Semaphore, current_thread
# import time
# import random
# sem = Semaphore(5)
#
# def task():
#     sem.acquire()
#
#     print(f'{current_thread().name} 廁所ing')
#     time.sleep(random.randint(1,3))
#
#     sem.release()
#
#
# if __name__ == '__main__':
#     for i in range(20):
#         t = Thread(target=task,)
#         t.start()
          
        

4.GIL全局解釋器鎖

4.1背景

          
            #理論上來說:單個進程的多線程可以利用多核.
          
        

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池_第2張圖片

          
            #但是,開發Cpython解釋器的程序員,給進入解釋器的線程加了鎖.
          
        

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池_第3張圖片

4.2為什么加鎖

          
            1. 當時都是單核時代,而且cpu價格非常貴.
2. 如果不加全局解釋器鎖, 開發Cpython解釋器的程序員就會在源碼內部各種主動加鎖,解鎖,非常麻煩,各種死鎖現象等等.他為了省事兒,直接進入解釋器時給線程加一個鎖.
   優點: 保證了Cpython解釋器的數據資源的安全.
   缺點: 單個進程的多線程不能利用多核.
#Jpython沒有GIL鎖.
#pypy也沒有GIL鎖.
#現在多核時代, 我將Cpython的GIL鎖去掉行么?
#因為Cpython解釋器所有的業務邏輯都是圍繞著單個線程實現的,去掉這個GIL鎖,幾乎不可能.

單個進程的多線程可以并發,但是不能利用多核,不能并行.
多個進程可以并發,并行.
          
        

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池_第4張圖片

5.GIL與Lock鎖的區別

          
            相同點: 都是同種鎖,互斥鎖.
不同點:
    GIL鎖全局解釋器鎖,保護解釋器內部的資源數據的安全. 
    GIL鎖 上鎖,釋放無需手動操作.
    自己代碼中定義的互斥鎖保護進程中的資源數據的安全.
    自己定義的互斥鎖必須自己手動上鎖,釋放鎖.
          
        

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池_第5張圖片

6.驗證計算密集型IO密集型的效率

6.1 IO密集型

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池_第6張圖片

          
            # IO密集型: 單個進程的多線程并發 vs 多個進程的并發并行

# def task():
#     count = 0
#     time.sleep(random.randint(1,3))
#     count += 1

# if __name__ == '__main__':

# 多進程的并發,并行
#     start_time = time.time()
#     l1 = []
#     for i in range(50):
#         p = Process(target=task,)
#         l1.append(p)
#         p.start()
#
#     for p in l1:
#         p.join()
#
#     print(f'執行效率:{time.time()- start_time}')  #  8.000000000

# 多線程的并發
#     start_time = time.time()
#     l1 = []
#     for i in range(50):
#         p = Thread(target=task,)
#         l1.append(p)
#         p.start()
#
#     for p in l1:
#         p.join()
#
#     print(f'執行效率:{time.time()- start_time}')  # 3.0294392108917236

對于IO密集型: 單個進程的多線程的并發效率高.
          
        

6.2 計算密集型

Python并發編程05/ 死鎖/遞歸鎖/信號量/GIL鎖/進程池/線程池_第7張圖片

          
            #from threading import Thread
#from multiprocessing import Process
#import time
#import random
# # 計算密集型: 單個進程的多線程并發 vs 多個進程的并發并行
#
# def task():
#     count = 0
#     for i in range(10000000):
#         count += 1
#
#
# if __name__ == '__main__':
#
#     # 多進程的并發,并行
#     # start_time = time.time()
#     # l1 = []
#     # for i in range(4):
#     #     p = Process(target=task,)
#     #     l1.append(p)
#     #     p.start()
#     #
#     # for p in l1:
#     #     p.join()
#     #
#     # print(f'執行效率:{time.time()- start_time}')  # 3.1402080059051514
#
#     # 多線程的并發
#     # start_time = time.time()
#     # l1 = []
#     # for i in range(4):
#     #     p = Thread(target=task,)
#     #     l1.append(p)
#     #     p.start()
#     #
#     # for p in l1:
#     #     p.join()
#     #
#     # print(f'執行效率:{time.time()- start_time}')  # 4.5913777351379395

總結: 計算密集型: 多進程的并發并行效率高.

          
        

7.多線程實現socket通信

          
            #無論是多線程還是多進程,如果按照上面的寫法,來一個客戶端請求,我就開一個線程,來一個請求開一個線程,

#應該是這樣: 你的計算機允許范圍內,開啟的線程進程數量越多越好.

          
        

7.1服務端

          
            # import socket
# from threading import Thread
#
# def communicate(conn,addr):
#     while 1:
#         try:
#             from_client_data = conn.recv(1024)
#             print(f'來自客戶端{addr[1]}的消息: {from_client_data.decode("utf-8")}')
#             to_client_data = input('>>>').strip()
#             conn.send(to_client_data.encode('utf-8'))
#         except Exception:
#             break
#     conn.close()
#
# def _accept():
#     server = socket.socket()
#     server.bind(('127.0.0.1', 8848))
#     server.listen(5)
#
#     while 1:
#         conn, addr = server.accept()
#         t = Thread(target=communicate,args=(conn,addr))
#         t.start()
#
# if __name__ == '__main__':
#     _accept()

          
        

7.2客戶端

          
            # import socket
# client = socket.socket()
# client.connect(('127.0.0.1',8848))
#
# while 1:
#     try:
#         to_server_data = input('>>>').strip()
#         client.send(to_server_data.encode('utf-8'))
#
#         from_server_data = client.recv(1024)
#         print(f'來自服務端的消息: {from_server_data.decode("utf-8")}')
#
#     except Exception:
#         break
# client.close()


          
        

8.進程池,線程池

          
            #線程池: 一個容器,這個容器限制住你開啟線程的數量,比如4個,第一次肯定只能并發的處理4個任務,只要有任務完成,線程馬上就會接下一個任務.

以時間換空間.

# from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
# import os
# import time
# import random
# 
# # print(os.cpu_count())
# def task(n):
#     print(f'{os.getpid()} 接客')
#     time.sleep(random.randint(1,3))
# 
# 
# if __name__ == '__main__':

    # 開啟進程池  (并行(并行+并發))
    # p = ProcessPoolExecutor()  # 默認不寫,進程池里面的進程數與cpu個數相等
    #
    # # p.submit(task,1)
    # # p.submit(task,1)
    # # p.submit(task,1)
    # # p.submit(task,1)
    # # p.submit(task,1)
    # # p.submit(task,1)
    # # p.submit(task,1)
    # for i in range(20):
    #     p.submit(task,i)
    #
    # 開啟線程池  (并發)
    # t = ThreadPoolExecutor()  # 默認不寫, cpu個數*5 線程數
    # t = ThreadPoolExecutor(100)  # 100個線程

    # for i in range(20):
    #     t.submit(task,i)

          
        

更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲国产欧美日韩 | 亚洲人成免费网站 | 成人短视频在线观看视频 | 99精品国产兔费观看66 | 国产精品揄拍100视频 | 国产伦理久久精品久久久久 | 久久免费视频播放 | 欧美日韩亚洲在线观看 | 久久精品国产亚洲片 | 午夜窝窝| 国产高清一级毛片在线不卡 | 久草美女视频 | 日韩国产欧美一区二区三区在线 | 欧美美女xnxx | 久久新 | 欧美日韩国产成人综合在线 | 精品一区二区久久 | 久久视频免费看 | 六月婷婷中文字幕 | 日本免费爱爱视频 | 日韩有码在线播放 | 国内精品免费网站牛牛 | 日韩欧美亚洲精品 | 色精品视频 | 精品一区二区三区 不卡高清 | 欧美日韩在线观看免费 | 久久日韩 | 91在线视频免费播放 | 日本在线观看不卡 | 午夜一区二区在线观看 | 欧美成人观看视频在线 | 中文乱码精品一区二区三区 | 狠狠操天天操视频 | 久久精品这里精品 | 国产精品伦一区二区三级视频 | 97视频网站 | 国产一区二区三区免费在线视频 | 久久久久国产精品四虎 | 久久99亚洲精品久久久久 | 国产精品久久久久9999高清 | 成人网视频在线观看免费 |