【乾貨】趣味詳解 3 種 Python 執行緒鎖
執行緒安全
- 執行緒1對num進行一千萬次+1的操作
- 執行緒2對num進行一千萬次-1的操作
import threading
num = 0
def add():
global num
for i in range(10_000_000):
num += 1
def sub():
global num
for i in range(10_000_000):
num -= 1
if __name__ == "__main__":
subThread01 = threading.Thread(target=add)
subThread02 = threading.Thread(target=sub)
subThread01.start()
subThread02.start()
subThread01.join()
subThread02.join()
print("num result : %s" % num)
# 結果三次採集
# num result : 669214
# num result : -1849179
# num result : -525674
鎖的作用
- 同步鎖:lock(一次只能放行一個)
- 遞迴鎖:rlock(一次只能放行一個)
- 條件鎖:condi on(一次可以放行任意個)
- 事件鎖:event(一次全部放行)
- 訊號量鎖:semaphore(一次可以放行特定個)
1、Lock() 同步鎖 基本介紹
- 同步鎖
- 互斥鎖
- 互斥指的是某一資源同一時刻僅能有一個訪問者對其進行訪問,具有唯一性和排他性,但是互斥無法限制訪問者對資源的訪問順序,即訪問是無序的
- 同步是指在互斥的基礎上(大多數情況),透過其他機制實現訪問者對資源的有序訪問
- 同步其實已經實現了互斥,是互斥的一種更為複雜的實現,因為它在互斥的基礎上實現了有序訪問的特點
方法描述
threading.Lock()返回一個同步鎖物件
lockObject.acquire(blocking=True, timeout=1)上鎖,當一個執行緒在執行被上鎖程式碼塊時,將不允許切換到其他執行緒執行,預設鎖失效時間為1秒
lockObject.release()解鎖,當一個執行緒在執行未被上鎖程式碼塊時,將允許系統根據策略自行切換到其他執行緒中執行
lockObject.locaked()判斷該鎖物件是否處於上鎖狀態,返回一個布林值
使用方式
import threading
num = 0
def add():
lock.acquire()
global num
for i in range(10_000_000):
num += 1
lock.release()
def sub():
lock.acquire()
global num
for i in range(10_000_000):
num -= 1
lock.release()
if __name__ == "__main__":
lock = threading.Lock()
subThread01 = threading.Thread(target=add)
subThread02 = threading.Thread(target=sub)
subThread01.start()
subThread02.start()
subThread01.join()
subThread02.join()
print("num result : %s" % num)
# 結果三次採集
# num result : 0
# num result : 0
# num result : 0
死鎖現象
import threading
num = 0
def add():
lock.acquire() # 上鎖
lock.acquire() # 死鎖
# 不執行
global num
for i in range(10_000_000):
num += 1
lock.release()
lock.release()
def sub():
lock.acquire() # 上鎖
lock.acquire() # 死鎖
# 不執行
global num
for i in range(10_000_000):
num -= 1
lock.release()
lock.release()
if __name__ == "__main__":
lock = threading.Lock()
subThread01 = threading.Thread(target=add)
subThread02 = threading.Thread(target=sub)
subThread01.start()
subThread02.start()
subThread01.join()
subThread02.join()
print("num result : %s" % num)
with語句
import threading
num = 0
def add():
with lock:
# 自動加鎖
global num
for i in range(10_000_000):
num += 1
# 自動解鎖
def sub():
with lock:
# 自動加鎖
global num
for i in range(10_000_000):
num -= 1
# 自動解鎖
if __name__ == "__main__":
lock = threading.Lock()
subThread01 = threading.Thread(target=add)
subThread02 = threading.Thread(target=sub)
subThread01.start()
subThread02.start()
subThread01.join()
subThread02.join()
print("num result : %s" % num)
# 結果三次採集
# num result : 0
# num result : 0
# num result : 0
2、RLock() 遞迴鎖
基本介紹
方法描述
threading.RLock()返回一個遞迴鎖物件
lockObject.acquire(blocking=True, timeout=1)上鎖,當一個執行緒在執行被上鎖程式碼塊時,將不允許切換到其他執行緒執行,預設鎖失效時間為1秒
lockObject.release()解鎖,當一個執行緒在執行未被上鎖程式碼塊時,將允許系統根據策略自行切換到其他執行緒中執行
lockObject.locaked()判斷該鎖物件是否處於上鎖狀態,返回一個布林值
使用方式
import threading
num = 0
def add():
lock.acquire()
lock.acquire()
global num
for i in range(10_000_000):
num += 1
lock.release()
lock.release()
def sub():
lock.acquire()
lock.acquire()
global num
for i in range(10_000_000):
num -= 1
lock.release()
lock.release()
if __name__ == "__main__":
lock = threading.RLock()
subThread01 = threading.Thread(target=add)
subThread02 = threading.Thread(target=sub)
subThread01.start()
subThread02.start()
subThread01.join()
subThread02.join()
print("num result : %s" % num)
# 結果三次採集
# num result : 0
# num result : 0
# num result : 0
with語句
import threading
num = 0
def add():
with lock:
# 自動加鎖
global num
for i in range(10_000_000):
num += 1
# 自動解鎖
def sub():
with lock:
# 自動加鎖
global num
for i in range(10_000_000):
num -= 1
# 自動解鎖
if __name__ == "__main__":
lock = threading.RLock()
subThread01 = threading.Thread(target=add)
subThread02 = threading.Thread(target=sub)
subThread01.start()
subThread02.start()
subThread01.join()
subThread02.join()
print("num result : %s" % num)
# 結果三次採集
# num result : 0
# num result : 0
# num result : 0
3、Condition() 條件鎖
基本介紹
方法描述
threading.Condition()返回一個條件鎖物件
lockObject.acquire(blocking=True, timeout=1)上鎖,當一個執行緒在執行被上鎖程式碼塊時,將不允許切換到其他執行緒執行,預設鎖失效時間為1秒
lockObject.release()解鎖,當一個執行緒在執行未被上鎖程式碼塊時,將允許系統根據策略自行切換到其他執行緒中執行
lockObject.wait(timeout=None)將當前執行緒設定為“等待”狀態,只有該執行緒接到“通知”或者超時時間到期之後才會繼續執行,在“等待”狀態下的執行緒將允許系統根據策略自行切換到其他執行緒中執行
lockObject.wait_for(predicate, timeout=None)將當前執行緒設定為“等待”狀態,只有該執行緒的predicate返回一個True或者超時時間到期之後才會繼續執行,在“等待”狀態下的執行緒將允許系統根據策略自行切換到其他執行緒中執行。注意:predicate引數應當傳入一個可呼叫物件,且返回結果為bool型別
lockObject.notify(n=1)通知一個當前狀態為“等待”的執行緒繼續執行,也可以透過引數n通知多個
lockObject.notify_all()通知所有當前狀態為“等待”的執行緒繼續執行
使用方式
import threading
currentRunThreadNumber = 0
maxSubThreadNumber = 10
def task():
global currentRunThreadNumber
thName = threading.currentThread().name
condLock.acquire() # 上鎖
print("start and wait run thread : %s" % thName)
condLock.wait() # 暫停執行緒執行、等待**
currentRunThreadNumber += 1
print("carry on run thread : %s" % thName)
condLock.release() # 解鎖
if __name__ == "__main__":
condLock = threading.Condition()
for i in range(maxSubThreadNumber):
subThreadIns = threading.Thread(target=task)
subThreadIns.start()
while currentRunThreadNumber < maxSubThreadNumber:
notifyNumber = int(
input("Please enter the number of threads that need to be notified to run:"))
condLock.acquire()
condLock.notify(notifyNumber) # 放行
condLock.release()
print("main thread run end")
# 先啟動10個子執行緒,然後這些子執行緒會全部變為等待狀態
# start and wait run thread : Thread-1
# start and wait run thread : Thread-2
# start and wait run thread : Thread-3
# start and wait run thread : Thread-4
# start and wait run thread : Thread-5
# start and wait run thread : Thread-6
# start and wait run thread : Thread-7
# start and wait run thread : Thread-8
# start and wait run thread : Thread-9
# start and wait run thread : Thread-10
# 批次傳送通知,放行特定數量的子執行緒繼續執行
# Please enter the number of threads that need to be notified to run:5 # 放行5個
# carry on run thread : Thread-4
# carry on run thread : Thread-3
# carry on run thread : Thread-1
# carry on run thread : Thread-2
# carry on run thread : Thread-5
# Please enter the number of threads that need to be notified to run:5 # 放行5個
# carry on run thread : Thread-8
# carry on run thread : Thread-10
# carry on run thread : Thread-6
# carry on run thread : Thread-9
# carry on run thread : Thread-7
# Please enter the number of threads that need to be notified to run:1
# main thread run end
with語句
import threading
currentRunThreadNumber = 0
maxSubThreadNumber = 10
def task():
global currentRunThreadNumber
thName = threading.currentThread().name
with condLock:
print("start and wait run thread : %s" % thName)
condLock.wait() # 暫停執行緒執行、等待**
currentRunThreadNumber += 1
print("carry on run thread : %s" % thName)
if __name__ == "__main__":
condLock = threading.Condition()
for i in range(maxSubThreadNumber):
subThreadIns = threading.Thread(target=task)
subThreadIns.start()
while currentRunThreadNumber < maxSubThreadNumber:
notifyNumber = int(
input("Please enter the number of threads that need to be notified to run:"))
with condLock:
condLock.notify(notifyNumber) # 放行
print("main thread run end")
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996125/viewspace-2847006/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JAVA多執行緒詳解(3)執行緒同步和鎖Java執行緒
- python中5種執行緒鎖Python執行緒
- iOS多執行緒安全-13種執行緒鎖?iOS執行緒
- python之執行緒鎖Python執行緒
- 高併發程式設計系列:4種Java執行緒鎖全面詳解程式設計Java執行緒
- java執行緒池趣味事:這不是執行緒池Java執行緒
- 執行緒安全: 互斥鎖和自旋鎖(10種)執行緒
- java--執行緒池--建立執行緒池的幾種方式與執行緒池操作詳解Java執行緒
- Python3中最常用的5種執行緒鎖你會用嗎Python執行緒
- Python程式和執行緒例項詳解Python執行緒
- .NET中各種執行緒同步鎖執行緒
- Python多執行緒與GIL鎖Python執行緒
- 多執行緒詳解執行緒
- 詳解多執行緒執行緒
- 多執行緒03:?執行緒傳參詳解執行緒
- java中常見的六種執行緒池詳解Java執行緒
- Mysql之鎖、事務絕版詳解---乾貨!MySql
- 乾貨:教你如何監控 Java 執行緒池執行狀態Java執行緒
- Java多執行緒(2)執行緒鎖Java執行緒
- python3 多執行緒Python執行緒
- 詳解Java執行緒安全Java執行緒
- iOS 多執行緒詳解iOS執行緒
- Java執行緒池詳解Java執行緒
- Java多執行緒詳解Java執行緒
- Java 執行緒池詳解Java執行緒
- java 執行緒淺解03[執行緒同步以及經典死鎖]Java執行緒
- 在netty3.x中存在兩種執行緒:boss執行緒和worker執行緒。Netty執行緒
- Python | 多執行緒死鎖問題的巧妙解決方法Python執行緒
- 執行緒鎖(四)執行緒
- 多執行緒_鎖執行緒
- java多執行緒與併發 - 執行緒池詳解Java執行緒
- 3種方式實現python多執行緒併發處理Python執行緒
- Android 多執行緒-----AsyncTask詳解Android執行緒
- mysql後臺執行緒詳解MySql執行緒
- iOS多執行緒:NSOperation詳解iOS執行緒
- iOS多執行緒:GCD詳解iOS執行緒GC
- JAVA多執行緒詳解(一)Java執行緒
- MySQL執行緒狀態詳解MySql執行緒