網站首頁 編程語言 正文
一、創建一個線程
- 通過實例化
threading.Thread
類創建線程
import threading def func(s): print(s) if __name__ == '__main__': # 創建線程 thread = threading.Thread(target=func, args=('hello',)) # 啟動線程 thread.start() # 等待線程結束 thread.join()
二、創建多個線程
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]
三、線程同步
- 使用鎖實現線程同步
-
threading.Lock
是直接通過_thread模塊擴展實現的 - 鎖只有“鎖定”和“非鎖定”兩種狀態
- 同一個線程獲取鎖后,如果在釋放鎖之前再次獲取鎖會導致當前線程阻塞,除非有另外的線程來釋放鎖,如果只有一個線程,并且發生了這種情況,會導致這個線程一直阻塞下去,即形成了死鎖。
import time import threading # 創建鎖 lock = threading.Lock() # 全局變量 global_resource = [None] * 5 def change_resource(para, sleep): # 請求鎖 lock.acquire() # 這段代碼如果不加鎖,第一個線程運行結束后global_resource中是亂的,輸出為:結果是: ['hello', 'hi', 'hi', 'hello', 'hello'] # 第二個線程運行結束后,global_resource中還是亂的,輸出為:結果是: ['hello', 'hi', 'hi', 'hi', 'hi'] global global_resource for i in range(len(global_resource)): global_resource[i] = para time.sleep(sleep) print("結果是:", 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] # 結果是: ['hi', 'hi', 'hi', 'hi', 'hi'] # 結果是: ['hello', 'hello', 'hello', 'hello', 'hello']
四、遞歸鎖
- 上面線程同步使用的是普通鎖,也就是只有鎖的狀態,并不知道是哪個線程加的鎖
- 這樣的話使用普通鎖時,對于一些可能造成死鎖的情況,可以考慮使用遞歸鎖來解決
- 遞歸鎖和普通鎖的差別在于加入了“所屬線程”和“遞歸等級”的概念
- 釋放鎖必須有獲取鎖的線程來進行釋放
import time import threading # 使用成一個遞歸鎖就可以解決當前這種死鎖情況 rlock_hi = rlock_hello = threading.RLock() def test_thread_hi(): # 初始時鎖內部的遞歸等級為1 rlock_hi.acquire() print('線程test_thread_hi獲得了鎖rlock_hi') time.sleep(2) # 如果再次獲取同樣一把鎖,則不會阻塞,只是內部的遞歸等級加1 rlock_hello.acquire() print('線程test_thread_hi獲得了鎖rlock_hello') # 釋放一次鎖,內部遞歸等級減1 rlock_hello.release() # 這里再次減,當遞歸等級為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]
五、信號鎖
- 一個信號量管理一個內部計數器
-
acquire()
方法會減少計數器,release()
方法則增加計數器 - 計數器的值永遠不會小于零
- 當調用
acquire()
時,如果發現該計數器為零,則阻塞線程 - 直到調用
release()
方法使計數器增加。
import time import threading # 創建信號量對象,初始化計數器值為3 semaphore3 = threading.Semaphore(3) def thread_semaphore(index): # 信號量計數器減1 semaphore3.acquire() time.sleep(2) print('thread_%s is running...' % index) # 信號量計數器加1 semaphore3.release() if __name__ == '__main__': # 雖然會有9個線程運行,但是通過信號量控制同時只能有3個線程運行 # 第4個線程啟動時,調用acquire發現計數器為0了,所以就會阻塞等待計數器大于0的時候 for index in range(9): threading.Thread(target=thread_semaphore, args=(index, )).start()
原文鏈接:https://blog.51cto.com/autofelix/5167799
相關推薦
- 2023-04-26 Python實現計算函數或程序執行時間_python
- 2023-01-03 Kotlin文件讀寫與SharedPreferences存儲功能實現方法_Android
- 2023-01-01 用幾行C#代碼實現定時關機/重啟(超詳細!建議新手練習)_C#教程
- 2022-07-26 Python使用psutil獲取系統信息_python
- 2022-12-04 React條件渲染實例講解使用_React
- 2022-05-03 詳解利用python-highcharts庫繪制交互式可視化圖表_python
- 2022-11-28 linux?iptables防火墻中的工作常用命令_linux shell
- 2022-07-30 使用logging模塊debug方法來調試代碼
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支