這篇文章主要為大家詳細 介紹了Python多執行緒中阻塞join與鎖Lock的使用誤區,具有一定的參考價值,有興趣的小夥伴們可以參考一下
關於阻塞主執行緒
##join的錯誤用法Thread.join() 作用為阻塞主執行緒,即在子執行緒未返回的時候,主執行緒等待其返回然後再繼續執行.
join不能與start在循環裡連用以下為錯誤代碼,代碼創建了5個線程,然後用一個循環激活線程,激活之後令其阻塞主線程.
threads = [Thread() for i in range(5)] for thread in threads: thread.start() thread.join()
2.由於start函數不會阻塞主執行緒,在執行緒1進行運算的同時,主執行緒向下執行join函數.
3. 執行join之後,主執行緒被執行緒1阻塞,在執行緒1回傳結果之前,主執行緒無法執行下一輪循環.
4. 線程1計算完成之後,解除對主線程的阻塞.
5. 主線程進入下一輪循環,激活線程2並被其阻塞…
join的正確用法
使用兩個循環分別處理start和join函數.即可實現並發.
##threads = [Thread() for i in range(5)] for thread in threads: thread.start() for thread in threads: thread.join()
time.sleep代替join進行調試
之前在一些項目裡看到過這樣的代碼,使用time.sleep代替join手動阻塞主線程.
在所有子線程返回之前,主線程陷入無線循環而不能退出.for thread in threads: thread.start() while 1: if thread_num == 0: break time.sleep(0.01)
單核心CPU PIL是否還需要鎖定?
非原子操作
count = count 1理論上是線程不安全的. 使用3個線程同時執行上述操作改變全域變數count的值,並查看程式執行結果. 如果結果正確,則表示未出現執行緒衝突.
使用下列程式碼測試
# -*- coding: utf-8 -*- import threading import time count = 0 class Counter(threading.Thread): def __init__(self, name): self.thread_name = name super(Counter, self).__init__(name=name) def run(self): global count for i in xrange(100000): count = count + 1 counters = [Counter('thread:%s' % i) for i in range(5)] for counter in counters: counter.start() time.sleep(5) print 'count=%s' % count
執行結果:
count=275552事實上每次運行結果都不相同且不正確,這證明單核心CPU PIL仍無法保證執行緒安全,需要加鎖.
加上鎖定後的正確程式碼:
# -*- coding: utf-8 -*- import threading import time count = 0 lock = threading.Lock() class Counter(threading.Thread): def __init__(self, name): self.thread_name = name self.lock = threading.Lock() super(Counter, self).__init__(name=name) def run(self): global count global lock for i in xrange(100000): lock.acquire() count = count + 1 lock.release() counters = [Counter('thread:%s' % i) for i in range(5)] for counter in counters: counter.start() time.sleep(5) print 'count=%s' % count
#結果:
count=500000
##注意鎖的全局性
這是一個簡單的Python語法問題,但在邏輯複雜時有可能被忽略.要保證鎖對於多個子線程來說是共用的,即不要在Thread的子類內部創建鎖定.
# -*- coding: utf-8 -*- import threading import time count = 0 # lock = threading.Lock() # 正确的声明位置 class Counter(threading.Thread): def __init__(self, name): self.thread_name = name self.lock = threading.Lock() # 错误的声明位置 super(Counter, self).__init__(name=name) def run(self): global count for i in xrange(100000): self.lock.acquire() count = count + 1 self.lock.release() counters = [Counter('thread:%s' % i) for i in range(5)] for counter in counters: print counter.thread_name counter.start() time.sleep(5) print 'count=%s' % count
python多執行緒之事件Event的使用詳解############python執行緒池threadpool的實作########################
以上是Python多執行緒中阻塞(join)與鎖(Lock)使用誤區解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!