日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

桐花万里python路-高级篇-并发编程-03-线程

發(fā)布時(shí)間:2025/3/21 python 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 桐花万里python路-高级篇-并发编程-03-线程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  • 理論
    • 進(jìn)程只是一個(gè)資源單位,線程才是cpu上的執(zhí)行單位
    • 無需申請(qǐng)空間,創(chuàng)建開銷小
    • 共享和創(chuàng)建開銷
      • 多線程共享一個(gè)進(jìn)程的地址空間
      • 線程比進(jìn)程更輕量級(jí),線程比進(jìn)程更容易創(chuàng)建可撤銷
      • I/O密集型,多線程,會(huì)加快程序執(zhí)行的速度
      • 在多cpu系統(tǒng)中,為了最大限度的利用多核,可以開啟多個(gè)線程,比開進(jìn)程開銷要小的多。(這一條并不適用于python)
  • 線程操作
    • 創(chuàng)建方式
      • from threading import Thread
      • t=Thread(target=func,args=('hello',)) ; t.start()
      • 繼承Thread類,實(shí)現(xiàn)run()方法
    • 其他方法
      • t.isAlive(): 返回線程是否活動(dòng)的
      • t.getName(): 返回線程名
      • t.setName(): 設(shè)置線程名
      • threading.currentThread(): 返回當(dāng)前的線程變量
      • threading.enumerate(): 返回一個(gè)包含正在運(yùn)行的線程的list
      • threading.activeCount(): 返回正在運(yùn)行的線程數(shù)量,與len(threading.enumerate())有相同的結(jié)果
    • 線程間關(guān)系
      • 串行 join
        • 主線程等待子線程結(jié)束?
        • 主線程所在的進(jìn)程內(nèi)所有非守護(hù)線程統(tǒng)統(tǒng)運(yùn)行完畢,主線程才算運(yùn)行完畢
      • 守護(hù)線程
        • t.daemon = True
        • 無論是進(jìn)程還是線程,都遵循:守護(hù)xxx會(huì)等待主xxx運(yùn)行完畢后被銷毀 1.對(duì)主進(jìn)程來說,運(yùn)行完畢指的是主進(jìn)程代碼運(yùn)行完畢 2.對(duì)主線程來說,運(yùn)行完畢指的是主線程所在的進(jìn)程內(nèi)所有非守護(hù)線程統(tǒng)統(tǒng)運(yùn)行完畢,主線程才算運(yùn)行完畢
  • 線程同步
    • Python的GIL
      • 在Cpython解釋器中,同一個(gè)進(jìn)程下開啟的多線程,同一時(shí)刻只能有一個(gè)線程執(zhí)行,無法利用多核優(yōu)勢(shì)
      • GIL本質(zhì)就是一把互斥鎖,保護(hù)不同的數(shù)據(jù)的安全,就應(yīng)該加不同的鎖。 將并發(fā)運(yùn)行變成串行,以此來控制同一時(shí)間內(nèi)共享數(shù)據(jù)只能被一個(gè)任務(wù)所修改,進(jìn)而保證數(shù)據(jù)安全
      • 在一個(gè)python的進(jìn)程內(nèi),不僅有主線程或者由該主線程開啟的其他線程,還有解釋器開啟的垃圾回收等解釋器級(jí)別的線程
      • 多個(gè)線程的target=work執(zhí)行流程
        • 多個(gè)線程先訪問到解釋器的代碼,即拿到執(zhí)行權(quán)限
          • 所有數(shù)據(jù)都是共享的,代碼作為一種數(shù)據(jù)也是被所有線程共享的
          • 所有線程的任務(wù),都需要將任務(wù)的代碼當(dāng)做參數(shù)傳給解釋器的代碼去執(zhí)行
        • 將target的代碼交給解釋器的代碼去執(zhí)行
      • 對(duì)計(jì)算來說,cpu越多越好,但是對(duì)于I/O來說,再多的cpu也沒用
        • IT(IO-Thread)多線程用于IO密集型,如socket,爬蟲,web
        • CP(Calculate-Process)多進(jìn)程用于計(jì)算密集型,如金融分析
      • 對(duì)于同一個(gè)數(shù)據(jù)100,可能線程1執(zhí)行x=100的同時(shí),而垃圾回收?qǐng)?zhí)行的是回收100的操作,解決這種問題沒有什么高明的方法,就是加鎖處理,如下圖的GIL,保證python解釋器同一時(shí)間只能執(zhí)行一個(gè)任務(wù)的代碼
    • 遞歸鎖 RLock
      • 死鎖: 兩個(gè)或兩個(gè)以上的進(jìn)程或線程在執(zhí)行過程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象
      • 在同一線程中多次請(qǐng)求同一資源,python提供了可重入鎖RLock
      • 內(nèi)部維護(hù)著一個(gè)Lock和一個(gè)counter變量
        • Counter記錄了acquire的次數(shù),從而使得資源可以被多次require
        • 直到一個(gè)線程所有的acquire都被release,其他的線程才能獲得資源
    • 信號(hào)量 Semaphore
      • 管理一個(gè)內(nèi)置的計(jì)數(shù)器
      • from threading import Thread,Semaphore
        • 預(yù)置量 sm=Semaphore(5)
        • 鎖定 sm.acquire()
        • 釋放?sm.release()
      • 會(huì)產(chǎn)生新的線程
    • 事件 Event
      • 通過判斷某個(gè)線程的狀態(tài),本質(zhì)是修改全局變量
      • 由線程設(shè)置的信號(hào)標(biāo)志,它允許線程等待某些事件的發(fā)生
      • 初始情況下,Event對(duì)象中的信號(hào)標(biāo)志被設(shè)置為假
      • 有線程等待一個(gè)Event對(duì)象, 而這個(gè)Event對(duì)象的標(biāo)志為假,那么這個(gè)線程將會(huì)被一直阻塞直至該標(biāo)志為真
      • 一個(gè)線程如果將一個(gè)Event對(duì)象的信號(hào)標(biāo)志設(shè)置為真,它將喚醒所有等待這個(gè)Event對(duì)象的線程
      • 如果一個(gè)線程等待一個(gè)已經(jīng)被設(shè)置為真的Event對(duì)象,那么它將忽略這個(gè)事件, 繼續(xù)執(zhí)行
      • 方法
        • event.isSet():返回event的狀態(tài)值
        • event.wait(timeout=3):如果 event.isSet()==False將阻塞線程,超時(shí)時(shí)間timeout
        • event.set(): 設(shè)置event的狀態(tài)值為True,所有阻塞池的線程激活進(jìn)入就緒狀態(tài), 等待操作系統(tǒng)調(diào)度
        • event.clear():恢復(fù)event的狀態(tài)值為False
    • 定時(shí)器
      • 指定n秒后執(zhí)行某操作
      • from threading import Timer
      • t = Timer(3, hello)
      • t.start()
  • 線程池
    • 線程queue
      • 使用import queue,用法與進(jìn)程Queue一樣
      • q=queue.Queue() 先進(jìn)先出
      • queue.LifoQueue(maxsize=0)? 后進(jìn)先出
      • queue.PriorityQueue(maxsize=0) 存儲(chǔ)數(shù)據(jù)時(shí)可設(shè)置優(yōu)先級(jí)的隊(duì)列
        • q.put((20,'a'))
        • 元組的第一個(gè)元素是優(yōu)先級(jí)(通常是數(shù)字,也可以是非數(shù)字之間的比較),數(shù)字越小優(yōu)先級(jí)越高
    • concurrent.futures
      •  高度封裝的異步調(diào)用接口
      • 線程池?ThreadPoolExecutor
        • max_workers :cpu_count*5
      • 進(jìn)程池?ProcessPoolExecutor
        • max_workers :cpu_count
      • 方法
        • submit(fn, *args, **kwargs)
        • map(func, *iterables, timeout=None, chunksize=1)?異步,須在shutdown之前
          • 循環(huán)submit
          • executor.map(task,range(1,12))? map取代了for+submit
        • shutdown(wait=True)
          • 相當(dāng)于進(jìn)程池的pool.close()+pool.join()操作
          • wait=True,等待池內(nèi)所有任務(wù)執(zhí)行完畢回收完資源后才繼續(xù)
          • wait=False,立即返回,并不會(huì)等待池內(nèi)的任務(wù)執(zhí)行完畢
        • result(timeout=None) 取得結(jié)果
        • add_done_callback(fn) 回調(diào)函數(shù)
          • p.submit(get_page,url).add_done_callback(parse_page)
          • parse_page拿到的是一個(gè)future對(duì)象obj,需要用obj.result()拿到結(jié)果 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutorimport os,time,random def task(n):print('%s is runing' %os.getpid())time.sleep(random.randint(1,3))return n**2if __name__ == '__main__':executor=ThreadPoolExecutor(max_workers=3)# for i in range(11):# future=executor.submit(task,i) executor.map(task,range(1,12)) #map取代了for+submit

            ?

轉(zhuǎn)載于:https://www.cnblogs.com/zhujingxiu/p/8601953.html

總結(jié)

以上是生活随笔為你收集整理的桐花万里python路-高级篇-并发编程-03-线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。