"""" Python中使用線程有兩種方式:函數或用類別來包裝線程物件。
1、 函數式:呼叫thread模組中的start_new_thread()函數來產生新執行緒。執行緒的結束可以等待執行緒自然結束,也可以在執行緒函數中呼叫thread.exit()或thread.exit_thread()方法。
import time
import thread
def timer(no,interval):
cnt=0
while cnt cnt= cnt+1
def test():
thread.start_new_thread(timer,(1,1))
thread.start_new_thread==(timer,(2,2))
thread.start_new_thread==(timer,(2,2))
thread.startname thread starting'
test()
time.sleep(20)
thread.exit_thread()
print 'exit...'
2、 建立一個建立一個子類別的子類別,Threadthread?使用:
1,在自己的線程類別的__init__裡調用threading.Thread.__init__(self, name = threadname)
Threadname為線程的名字
2, run(),通常需要重寫,寫程式碼實現做需要的功能。
3,getName(),取得執行緒物件名稱
4,setName(),設定執行緒物件名稱
5,start(),啟動執行緒
6,jion([timeout]),等待另一個執行緒結束後再運行。
7,setDaemon(bool),設定子執行緒是否隨主執行緒一起結束,必須在start()之前呼叫。預設為False。
8,isDaemon(),判斷執行緒是否隨主執行緒一起結束。
9,isAlive(),檢查執行緒是否在運作中。
import threading
import time
class timer(threading.Thread):
def __init__(self,num,interval): sel.
self.interval=interval
self .thread_stop=False
def run(self):
while not self.thread_stop:
time.sleep( self.interval)
def stop(self):
self.thread_stop=True
def test(): 我()
thread2.start()
time.sleep(10)
thread1.stop()
thread2.stop()
return
if __name__=='main:
問題產生的原因是沒有控制多個執行緒對相同資源的訪問,對資料造成破壞,使得執行緒運行的結果不可預期。這種現象稱為「線程不安全」。
import threading
import time
class MyThread(threading.Thread):
def run(self):
sg='I am '+ self.getName ()+'@'+str(i)
print msg
def test():
for i in range(5):
__Thread() ':
test()
上面的範例引出了多執行緒程式設計最常見的問題:資料共享。當多個執行緒都修改某一個共享資料的時候,就需要進行同步控制。
執行緒同步能夠確保多個執行緒安全存取競爭資源,最簡單的同步機制是引入互斥鎖。互斥鎖為資源引入一個狀態:鎖定/非鎖定。某個執行緒要更改共享資料時,先將其鎖定,此時資源的狀態為“鎖定”,其他執行緒不能更改;直到該執行緒釋放資源,將資源的狀態變成“非鎖定”,其他的執行緒才能再次鎖定該資源。互斥鎖保證了每次只有一個執行緒進行寫入操作,從而保證了多執行緒情況下資料的正確性。其中,鎖定方法acquire可以有一個超時時間的可選參數timeout。如果設定了timeout,則在逾時後透過回傳值可以判斷是否得到了鎖,從而可以進行一些其他的處理
threading模組中定義了Lock類
import threading
import time
class MyThread(threading.Thread ):
def run(self):
global num
time.sleep(1)
if mutex.acquire():
num=num+1
mutex.release()
num=0
mutex=threading.Lock()
def test():
for i in range(5):
t=MyThread() test()
"""
"""更簡單的死鎖情況是一個執行緒「迭代」請求相同資源,直接就會造成死鎖:
import threading
import time
class MyThread(threading.Thread)(threading.Thread) :
def run(self):
global num
num = num+1
msg = self.name+' set num to '+str(num)
print msg
mutex.acquire() mutex.release()
num = 0
mutex = threading.Lock()
def test():
for i in range(5): = MyThread()
t.start()
if __name__ == '__main__':
test()
為了支援在同一執行緒中多次要求相同資源,python」提供了「可重複鎖定了. RLock內部維護一個Lock和一個counter變量,counter記錄了acquire的次數,從而使得資源可以被多次require。直到一個線程所有的acquire都被release,其他的線程才能獲得資源。上述的例子如果使用RLock代替Lock,則不會發生死鎖:
import threading
import time
class MyThread(threading.Thread):
def run(self): time.sleep(1)
if mutex.acquire(1):
(1): print msg
mutex.acquire()
mutex.release ()
num = 0
mutex = threading.RLock()
def test():
for i in range(5):
__name__ == '__main__':
test()
"""
"""
python多執行緒程式設計(5): 條件變數同步
互斥鎖定是最簡單的執行緒同步問題的支持。 Condition被稱為條件變量,除了提供與Lock類似的acquire和release方法外,還提供了wait和notify方法。線程先acquire一個條件變量,然後再判斷一些條件。如果條件不滿足則wait;如果條件滿足,進行一些處理改變條件後,透過notify方法通知其他線程,其他處於wait狀態的線程接到通知後會重新判斷條件。不斷的重複這個過程,從而解決複雜的同步問題。
可以認為Condition物件維護了一個鎖定(Lock/RLock)和一個waiting池。執行緒透過acquire取得Condition對象,當呼叫wait方法時,執行緒會釋放Condition內部的鎖定並進入blocked狀態,同時在waiting池中記錄這個執行緒。當呼叫notify方法時,Condition物件會從waiting池中挑選一個線程,通知其呼叫acquire方法嘗試取到鎖。
Condition物件的建構子可以接受一個Lock/RLock物件作為參數,如果沒有指定,則Condition物件會在內部自行建立一個RLock。
除了notify方法外,Condition物件還提供了notifyAll方法,可以通知waiting池中的所有執行緒嘗試acquire內部鎖定。由於上述機制,處於waiting狀態的執行緒只能透過notify方法喚醒,所以notifyAll的作用在於防止有執行緒永遠處於沉默狀態。
簡報條件變數同步的經典問題是生產者與消費者問題:假設有一群生產者(Producer)和一群消費者(Consumer)透過一個市場來互動產品。生產者的」策略「是如果市場上剩餘的產品少於1000個,那麼就生產100個產品放到市場上;而消費者的」策略「是如果市場上剩餘產品的數量多餘100個,那麼就消費3個產品。使用Condition解決生產者與消費者問題的代碼如下:
import threading
import time
class Producer(threading.Thread):
if con.acquire() :
if count>1000:
con.wait()
print self.name+' produce 100,count='+str(count)
(1)
class Customer(threading.Thread):
def run(self):
global count
count>100:
count=count-100
print self .name+ 'consume 100, count='+str(count)
else:
time.sleep(1)
count=500
con=threading.Condition()
def test():
for i in range(5):
p=Producer()
p.start()
if __name__==' __main__':
test()
python中預設全域變數在函數中可以讀,但是不能寫但是
對con只讀,所以不用global引入"""