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

歡迎訪問 生活随笔!

生活随笔

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

python

python之进程和线程2

發(fā)布時(shí)間:2025/7/25 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python之进程和线程2 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1? GIL全局解釋器鎖定義

定義:在一個(gè)線程擁有了解釋器的訪問權(quán)后,其他的所有線程都必須等待他釋放解釋器的訪問權(quán),即這些線程的下一條指令并不會(huì)互相影響。

缺點(diǎn):多處理器退化為單處理器

優(yōu)點(diǎn):避免大量的加鎖解鎖操作

?

?

無論你啟多少個(gè)線程,你有多少個(gè)cpu,python在執(zhí)行一個(gè)進(jìn)程的時(shí)候會(huì)淡定的在同一時(shí)刻只允許一個(gè)線程運(yùn)行。

Python是無法利用多核cpu實(shí)現(xiàn)多線程的

總結(jié):

對(duì)于計(jì)算密集型任務(wù),python的多線程并沒有用

對(duì)于IO密集型任務(wù),python的多線程是有意義的

python使用多核:開進(jìn)程,弊端:開銷大而且切換復(fù)雜

著重點(diǎn):協(xié)程+多進(jìn)程

方向:IO多路復(fù)用

終極思路:換C模塊實(shí)現(xiàn)多線程

2? 同步鎖

鎖通常被用來實(shí)現(xiàn)對(duì)共享資源的同步訪問,為每一個(gè)共享資源創(chuàng)建一個(gè)Lock對(duì)象,當(dāng)你需要訪問該資源時(shí),調(diào)用acquire方法來獲取鎖對(duì)象(如果其他線程已經(jīng)獲得了該鎖,則當(dāng)前線程需等待其被釋放),待資源訪問完,再調(diào)用release方法釋放鎖:

import time import threadingdef addNum():global num #在每個(gè)線程中都獲取這個(gè)全局變量#num-=1 #獲取的值為0 與temp=num num=temp-1是同一個(gè)意思 唯一在于time.sleep()lock.acquire()#添加鎖temp=numtime.sleep(0.001)#IO操作 如果時(shí)間在0.1時(shí),足夠讓一條線程完成后再走另一條線程 取值從100開始,99#如果時(shí)間為0.001時(shí),100條線程運(yùn)行時(shí)出現(xiàn)不確定性,有可能走到第五條的時(shí)候就完成IO操作,前五條基數(shù)為100,第六條基數(shù)就是99num =temp-1 # 對(duì)此公共變量進(jìn)行-1操作lock.release()#解鎖 num = 100 #設(shè)定一個(gè)共享變量thread_list = [] lock=threading.Lock()#獲取一把鎖 for i in range(100):t = threading.Thread(target=addNum)t.start()thread_list.append(t)for t in thread_list: #等待所有線程執(zhí)行完畢t.join()print('Result: ', num)

 

3 死鎖和遞歸鎖

死鎖就是指兩個(gè)或者兩個(gè)以上進(jìn)程或線程在執(zhí)行過程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無外力作用,他們都將無法推進(jìn)下去。此時(shí)稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖這些永遠(yuǎn)在互相等待的進(jìn)程被稱為死鎖進(jìn)程。

import threading import timemutexA = threading.Lock() mutexB = threading.Lock()class MyThread(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):self.fun1()self.fun2()def fun1(self):mutexA.acquire() # 如果鎖被占用,則阻塞在這里,等待鎖的釋放print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time()))mutexB.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time()))mutexB.release()mutexA.release()def fun2(self):mutexB.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time()))time.sleep(0.2)mutexA.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time()))mutexA.release()mutexB.release()if __name__ == "__main__":print("start---------------------------%s"%time.time())for i in range(0, 10):my_thread = MyThread()my_thread.start()

  

遞歸鎖

Python中為了支持在同一線程中多次請(qǐng)求統(tǒng)一資源,python提供了可重入鎖RLock。這個(gè)RLock內(nèi)部維護(hù)著一個(gè)Lock和一個(gè)counter變量,counter記錄了acquire的次數(shù),從而使得資源可以被多次require。直到一個(gè)線程所有的acpuire都被release,其他的線程才能獲得資源。

遞歸鎖用來解決死鎖

import threading import time Rlock=threading.RLock()#生成一個(gè)遞歸鎖 class MyThread(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):self.fun1()self.fun2()def fun1(self):Rlock.acquire() # 一條線程運(yùn)行,其他線程等待 count=1print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time()))Rlock.acquire()#同一條線程運(yùn)行,其他線程等待中。。。count=2,遞歸鎖print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time()))Rlock.release()#同一線程運(yùn)行完成后,count=1Rlock.release()#同一線程運(yùn)行完成后,count=0 ,其他線程才能獲得資源def fun2(self):Rlock.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time()))Rlock.acquire()print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time()))Rlock.release()Rlock.release()if __name__ == "__main__":print("start---------------------------%s"%time.time())for i in range(0, 10):my_thread = MyThread()my_thread.start()

 

4 Event對(duì)象

線程的一個(gè)關(guān)鍵特性是每個(gè)線程都是獨(dú)立運(yùn)行且狀態(tài)不可預(yù)測(cè)。如果程序中的其他線程需要通過判斷某個(gè)線程的狀態(tài)來確定自己下一步的操作,這時(shí)線程同步問題就會(huì)變得棘手,為了解決這些問題,我們需要使用threading庫中的Event對(duì)象。對(duì)象包含一個(gè)可由線程設(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對(duì)象 線程之間的簡(jiǎn)單通信 event.set()更改標(biāo)志位為True, 所有阻塞池的線程激活進(jìn)入就緒狀態(tài), 等待操作系統(tǒng)調(diào)度 event.wait()等待;還可以接收一個(gè)超時(shí)參數(shù),默認(rèn)情況下超過這個(gè)參數(shù)設(shè)定的值之后,wait方法會(huì)返回 event.clear()恢復(fù)event的狀態(tài)值為False event.isSet():返回event的狀態(tài)值

  

右邊的線程需要左邊線程運(yùn)行的時(shí)候,用Event.set來更改狀態(tài),為True;

如果右邊的線程狀態(tài)一直為默認(rèn)為假,左邊的線程則一直等待,不會(huì)執(zhí)行。

應(yīng)用場(chǎng)景:

我們有多個(gè)線程從Redis隊(duì)列中讀取數(shù)據(jù)來處理,這些線程都要嘗試去連接Redis的服務(wù),一般情況下,如果Redis連接不成功,在各個(gè)線程的代碼中,都會(huì)去嘗試重新連接。如果我們想要在啟動(dòng)時(shí)確保Redis服務(wù)正常,才讓那些工作線程去連接Redis服務(wù)器,那么我們就可以采用threading.Event機(jī)制來協(xié)調(diào)各個(gè)工作線程的連接操作:主線程中會(huì)去嘗試連接Redis服務(wù),如果正常的話,觸發(fā)事件,各工作線程會(huì)嘗試連接Redis服務(wù)。

import threading import time import logginglogging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s',)def worker(event):logging.debug('Waiting for redis ready...')event.wait()#由于狀態(tài)默認(rèn)為假,需等待logging.debug('redis ready, and connect to redis server and do some work [%s]', time.ctime())time.sleep(1)def main():#主函數(shù)readis_ready = threading.Event()t1 = threading.Thread(target=worker, args=(readis_ready,), name='t1')#產(chǎn)生一個(gè)對(duì)象t1.start()#開始運(yùn)行t2 = threading.Thread(target=worker, args=(readis_ready,), name='t2')t2.start()#產(chǎn)生一個(gè)對(duì)象logging.debug('first of all, check redis server, make sure it is OK, and then trigger the redis ready event')time.sleep(3) # simulate the check progressreadis_ready.set()#更改狀態(tài)為True,默認(rèn)為Falseif __name__=="__main__":main()

   

5 Semaphore(信號(hào)量)

Semaphore管理一個(gè)內(nèi)置的計(jì)數(shù)器,

每當(dāng)調(diào)用acquire()時(shí)內(nèi)置計(jì)數(shù)器-1;

調(diào)用release() 時(shí)內(nèi)置計(jì)數(shù)器+1;

計(jì)數(shù)器不能小于0;當(dāng)計(jì)數(shù)器為0時(shí),acquire()將阻塞線程直到其他線程調(diào)用release()。

?

實(shí)例:(同時(shí)只有5個(gè)線程可以獲得semaphore,即可以限制最大連接數(shù)為5):

import threading import time semaphore = threading.Semaphore(5) def func():semaphore.acquire()print (threading.currentThread().getName() + ' get semaphore')time.sleep(2)semaphore.release() for i in range(20):#總數(shù)為20,最大連接為5,分為4次t1 = threading.Thread(target=func)t1.start()

  

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

總結(jié)

以上是生活随笔為你收集整理的python之进程和线程2的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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