Python多執行緒中阻塞(join)與鎖(Lock)的使用誤區
關於阻塞主執行緒
join的錯誤用法
Thread.join()
作用為阻塞主執行緒,即在子執行緒未返回的時候,主執行緒等待其返回然後再繼續執行.
join不能與start在迴圈裡連用
以下為錯誤程式碼,程式碼建立了5個執行緒,然後用一個迴圈啟用執行緒,啟用之後令其阻塞主執行緒.
threads = [Thread() for i in range(5)]
for thread in threads:
thread.start()
thread.join()
執行過程:
1. 第一次迴圈中,主執行緒通過start函式啟用執行緒1,執行緒1進行計算.
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)
關於執行緒鎖(threading.Lock)
單核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多執行緒中阻塞(join)與鎖(Lock)的使用誤區
關於阻塞主執行緒 join的錯誤用法 Thread.join() 作用為阻塞主執行緒,即在子執行緒未返回的時候,主執行緒等待其返回然後再繼續執行. join不能與start在迴圈裡連用 以下為錯誤程式碼,程式碼建立了5個執行緒,然後用一個迴圈啟用執行緒,
Python多執行緒中的join函式的使用與含義
wechat:812716131 ------------------------------------------------------ 技術交流群請聯絡上面wechat ----------------------------------------------
徹底理解Python多執行緒中的setDaemon與join【配有GIF示意】
在進行Python多執行緒程式設計時, join() 和 setDaemon() 是最常用的方法,下面說說兩者的用法和區別。 1、join () 例子:主執行緒A中,建立了子執行緒B,並且在主執行緒A中呼叫了B.join(), 那麼,主執行緒A會在呼叫的地方阻塞,
python多執行緒中的join()
先看一個例子,該例子沒用到join。 新增一個執行緒,輸出“start”和“finish”標記執行緒的開始和結束。執行緒added_thread和執行緒main同時執行,其中added_thread消耗較長的時間(通過執行緒sleep模擬)。mian執行結束後
Python多執行緒中join函式與setDaemon函式使用說明
在Python多執行緒程式設計的時候,經常需要用到join函式和setDaemon函式。之前對這兩個函式一直理解不是很到位。今天查閱了很多資料,對兩個函式的認識更加的深入一些了。 join([timeout])可以參考Python文件說明。大概意思就
多執行緒中的join(),yield()與優先順序Priority
1、join():join()方法使呼叫該方法的執行緒在此之前執行完畢,也就是等待該方法的執行緒執行完畢後再往下繼續執行。注意該方法也需要捕捉異常。 ublic class Test { public static void main(String[] args) {
python多執行緒中daemon的屬性方法
我們看官方介紹是這樣的: 意思就是說:這個屬性為一個布林值,表示是否為一個守護程序,且這個屬性設定必須線上程的start方法開始之前呼叫。它的值繼承自主執行緒,主執行緒的daemon為False且所有從主執行緒建立的執行緒都是daemon = False 。 下面一句
多執行緒中的wait與sleep到底誰釋放了鎖
首先,多執行緒中會使用到兩個延遲的函式,wait和sleep。 wait是Object類中的方法,而sleep是Thread類中的方法。 sleep是Thread類中的靜態方法。無論是在a執行緒中呼
java多執行緒中關於join方法的使用
Thread的非靜態方法join()讓一個執行緒B“加入”到另外一個執行緒A的尾部。在A執行完畢之前,B不能工作。例如: Thread t = new MyThread(); t.start(); t.join(); 另外,j
java多執行緒中對於join方法的理解
對於多執行緒的join方法一直理解得很模糊,大致看了一些資料,JDK是這樣說的:join public final void join (long millis )throws InterruptedException Waits at most millis
Java多執行緒中,Join和Interrupt()方法的使用
更多詳細的解答請轉至:http://my.oschina.net/summerpxy/blog/198457;http://uule.iteye.com/blog/1101994;(比如有一個執行緒t.當在Main執行緒中呼叫t.join()的時候,那麼Main執行緒必須拿
java多執行緒中的join方法詳解
方法Join是幹啥用的? 簡單回答,同步,如何同步? 怎麼實現的? 下面將逐個回答。 自從接觸Java多執行緒,一直對Join理解不了。JDK是這樣說的:join public final void join(long millis)throws InterruptedException Wait
多執行緒中的join方法——原始碼分析
join方法的作用是等待執行緒銷燬,當主執行緒中呼叫了其他執行緒的join方法時,主執行緒需要等到該執行緒執行完畢才可以繼續執行,示例如下: public class MyThread extends Thread { public void ru
執行緒中的wait() 與 鎖的關係
我們先看一段程式碼: /** * 計算輸出其他執行緒鎖計算的資料 * */ public class ThreadA { public static void main(String[] args) throws InterruptedException{ Thre
python多執行緒和GIL全域性直譯器鎖
1、執行緒 執行緒被稱為輕量級程序,是最小執行單元,系統排程的單位。執行緒切換需要的資源一般,效率一般。 2、多執行緒 在單個程式中同時執行多個執行緒完成不同的工作,稱為多執行緒 3、
Python多執行緒讀寫檔案加鎖
Python的多執行緒在io方面比單執行緒還是有優勢,但是在多執行緒開發時,少不了對檔案的讀寫操作。在管理多個執行緒對同一檔案的讀寫操作時,就少不了檔案鎖了。 使用fcntl 在linux下,python的標準庫有現成的檔案鎖,來自於fcntl模組。這個模組提供了unix
Java多執行緒中的物件互斥鎖
1、為什麼會有鎖? 在看執行緒同步的問題之前,我們先看一個生活中的小例子: 我拿著銀行卡去ATM取錢,假如我的卡里有3000塊,我要取走2000,這個時候,ATM會去銀行的資料庫裡查詢我的賬戶是否有2000以上的餘額,如果有,就會讓我取走,不幸的是,這個時候
python多執行緒程式設計(3): 使用互斥鎖同步執行緒
問題的提出 上一節的例子中,每個執行緒互相獨立,相互之間沒有任何關係。現在假設這樣一個例子:有一個全域性的計數num,每個執行緒獲取這個全域性的計數,根據num進行一些處理,然後將num加1。很容易寫出這樣的程式碼: # encoding: UTF-8import
python中多執行緒中event的使用-----------------即一個靈活的方法標誌位,類似於java的等待喚醒機制(python與java不同的地方)
event是python中一個特有的標誌位方法,他一共有三種方法 1.event.wait():如果標誌位設定了,它不做任何事,如果沒有設定,則將會鎖住,等待標誌位的設定 2.event.set():設定標誌位 3.event.clear():清除標誌位 這一種機制很
多執行緒中sleep() wait() yield() join(), interrupt(),stop(),suspend()用法與區別
網上卻是有很多的關於這個的答案,但是都長得一樣,為了寫這篇部落格,自己找了幾個例子。 JoinThread: package com.com.aaa.threadJoinDemo; public c