python?包之?threading?多線程
更新時間:2022年04月02日 10:56:56 作者:autofelix
這篇文章主要介紹了python?包之?threading?多線程,文章通過實例化threading.Thread類創(chuàng)建線程,下文相關(guān)資料介紹,需要的朋友可以參考一下
一、創(chuàng)建一個線程
- 通過實例化
threading.Thread
類創(chuàng)建線程
import threading def func(s): print(s) if __name__ == '__main__': # 創(chuàng)建線程 thread = threading.Thread(target=func, args=('hello',)) # 啟動線程 thread.start() # 等待線程結(jié)束 thread.join()
二、創(chuàng)建多個線程
import threading def func(s): print(s) if __name__ == '__main__': thread = [ threading.Thread(target=func, args=('1', )) threading.Thread(target=func, args=('2', )) ] [t.start() for t in thread] [t.join() for t in thread]
三、線程同步
- 使用鎖實現(xiàn)線程同步
threading.Lock
是直接通過_thread模塊擴(kuò)展實現(xiàn)的- 鎖只有“鎖定”和“非鎖定”兩種狀態(tài)
- 同一個線程獲取鎖后,如果在釋放鎖之前再次獲取鎖會導(dǎo)致當(dāng)前線程阻塞,除非有另外的線程來釋放鎖,如果只有一個線程,并且發(fā)生了這種情況,會導(dǎo)致這個線程一直阻塞下去,即形成了死鎖。
import time import threading # 創(chuàng)建鎖 lock = threading.Lock() # 全局變量 global_resource = [None] * 5 def change_resource(para, sleep): # 請求鎖 lock.acquire() # 這段代碼如果不加鎖,第一個線程運行結(jié)束后global_resource中是亂的,輸出為:結(jié)果是: ['hello', 'hi', 'hi', 'hello', 'hello'] # 第二個線程運行結(jié)束后,global_resource中還是亂的,輸出為:結(jié)果是: ['hello', 'hi', 'hi', 'hi', 'hi'] global global_resource for i in range(len(global_resource)): global_resource[i] = para time.sleep(sleep) print("結(jié)果是:", global_resource) # 釋放鎖 lock.release() if __name__ == '__main__': thread = [ threading.Thread(target=change_resource, args=('hi', 2)) threading.Thread(target=change_resource, args=('hello', 1)) ] [t.start() for t in thread] [t.join() for t in thread] # 結(jié)果是: ['hi', 'hi', 'hi', 'hi', 'hi'] # 結(jié)果是: ['hello', 'hello', 'hello', 'hello', 'hello']
四、遞歸鎖
- 上面線程同步使用的是普通鎖,也就是只有鎖的狀態(tài),并不知道是哪個線程加的鎖
- 這樣的話使用普通鎖時,對于一些可能造成死鎖的情況,可以考慮使用遞歸鎖來解決
- 遞歸鎖和普通鎖的差別在于加入了“所屬線程”和“遞歸等級”的概念
- 釋放鎖必須有獲取鎖的線程來進(jìn)行釋放
import time import threading # 使用成一個遞歸鎖就可以解決當(dāng)前這種死鎖情況 rlock_hi = rlock_hello = threading.RLock() def test_thread_hi(): # 初始時鎖內(nèi)部的遞歸等級為1 rlock_hi.acquire() print('線程test_thread_hi獲得了鎖rlock_hi') time.sleep(2) # 如果再次獲取同樣一把鎖,則不會阻塞,只是內(nèi)部的遞歸等級加1 rlock_hello.acquire() print('線程test_thread_hi獲得了鎖rlock_hello') # 釋放一次鎖,內(nèi)部遞歸等級減1 rlock_hello.release() # 這里再次減,當(dāng)遞歸等級為0時,其他線程才可獲取到此鎖 rlock_hi.release() def test_thread_hello(): rlock_hello.acquire() print('線程test_thread_hello獲得了鎖rlock_hello') time.sleep(2) rlock_hi.acquire() print('線程test_thread_hello獲得了鎖rlock_hi') rlock_hi.release() rlock_hello.release() if __name__ == '__main__': thread = [ threading.Thread(target=test_thread_hi) threading.Thread(target=test_thread_hello) ] [t.start() for t in thread] [t.join() for t in thread]
五、信號鎖
- 一個信號量管理一個內(nèi)部計數(shù)器
acquire()
方法會減少計數(shù)器,release()
方法則增加計數(shù)器- 計數(shù)器的值永遠(yuǎn)不會小于零
- 當(dāng)調(diào)用
acquire()
時,如果發(fā)現(xiàn)該計數(shù)器為零,則阻塞線程 - 直到調(diào)用
release()
方法使計數(shù)器增加。
import time import threading # 創(chuàng)建信號量對象,初始化計數(shù)器值為3 semaphore3 = threading.Semaphore(3) def thread_semaphore(index): # 信號量計數(shù)器減1 semaphore3.acquire() time.sleep(2) print('thread_%s is running...' % index) # 信號量計數(shù)器加1 semaphore3.release() if __name__ == '__main__': # 雖然會有9個線程運行,但是通過信號量控制同時只能有3個線程運行 # 第4個線程啟動時,調(diào)用acquire發(fā)現(xiàn)計數(shù)器為0了,所以就會阻塞等待計數(shù)器大于0的時候 for index in range(9): threading.Thread(target=thread_semaphore, args=(index, )).start()
到此這篇關(guān)于python 包之 threading 多線程的文章就介紹到這了,更多相關(guān)threading 多線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python連接mongodb操作數(shù)據(jù)示例(mongodb數(shù)據(jù)庫配置類)
這篇文章主要介紹了python連接mongodb操作數(shù)據(jù)示例,主要包括插入數(shù)據(jù)、更新數(shù)據(jù)、查詢數(shù)據(jù)、刪除數(shù)據(jù)等2013-12-12DataFrame數(shù)據(jù)框模糊查詢與去重方式
數(shù)據(jù)框模糊查詢通常使用contains函數(shù)和正則表達(dá)式來實現(xiàn),可以查詢以某個字符開頭、包含或結(jié)尾的數(shù)據(jù),若數(shù)據(jù)類型不一致可能會報錯,需統(tǒng)一為str類型,數(shù)據(jù)框去重則通過drop_duplicates函數(shù)實現(xiàn),可指定列進(jìn)行去重,并有多種處理重復(fù)值的方式2024-09-09