python thread practices

來源:互聯網
上載者:User
"""" Python中使用線程有兩種方式:函數或者用類來封裝線程對象。

1、 函數式:調用thread模組中的start_new_thread()函數來產生新線程。線程的結束可以等待線程自然結束,也可以線上程函數中調用thread.exit()或thread.exit_thread()方法。
import time
import thread

def timer(no,interval):
cnt=0

while cnt<10:
print 'thread(%d)'%(cnt)
time.sleep(interval)
cnt=cnt+1


def test():
thread.start_new_thread(timer,(1,1))
thread.start_new_thread(timer,(2,2))

if __name__=='__main__':
print 'thread starting'
test()
time.sleep(20)
thread.exit_thread()
print 'exit...'
2、 建立threading.Thread的子類來封裝一個線程對象,
threading.Thread類的使用:

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):
threading.Thread.__init__(self)
self.thread_num=num
self.interval=interval
self.thread_stop=False

def run(self):
while not self.thread_stop:
print 'thread object (%d), time %s\n' %(self.thread_num,time.ctime())
time.sleep(self.interval)

def stop(self):
self.thread_stop=True

def test():
thread1=timer(1,1)
thread2=timer(2,2)
thread1.start()
thread2.start()
time.sleep(10)
thread1.stop()
thread2.stop()
return

if __name__=='__main__':
test()
"""
"""
問題產生的原因就是沒有控制多個線程對同一資源的訪問,對資料造成破壞,使得線程啟動並執行結果不可預期。這種現象稱為“線程不安全”。
import threading
import time

class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg='I am '+ self.getName()+'@'+str(i)
print msg

def test():
for i in range(5):
t=MyThread()
t.start()

if __name__=='__main__':
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
print self.name+' set num to '+str(num)+'\n'
mutex.release()
num=0
mutex=threading.Lock()

def test():
for i in range(5):
t=MyThread()
t.start()

if __name__=='__main__':
test()
"""
"""更簡單的死結情況是一個線程“迭代”請求同一個資源,直接就會造成死結:
import threading
import time

class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)

if mutex.acquire(1):
num = num+1
msg = self.name+' set num to '+str(num)
print msg
mutex.acquire()
mutex.release()
mutex.release()
num = 0
mutex = threading.Lock()
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
為了支援在同一線程中多次請求同一資源,python提供了“可重新進入鎖”:threading.RLock。RLock內部維護著一個Lock和一個counter變數,counter記錄了acquire的次數,從而使得資源可以被多次require。直到一個線程所有的acquire都被release,其他的線程才能獲得資源。上面的例子如果使用RLock代替Lock,則不會發生死結:
import threading
import time

class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)

if mutex.acquire(1):
num = num+1
msg = self.name+' set num to '+str(num)
print msg
mutex.acquire()
mutex.release()
mutex.release()
num = 0
mutex = threading.RLock()
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
"""

"""
python多線程編程(5): 條件變數同步

互斥鎖是最簡單的線程同步機制,Python提供的Condition對象提供了對複雜線程同步問題的支援。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):
def run(self):
global count
while True:
if con.acquire():
if count>1000:
con.wait()
else:
count=count+100
print self.name+' produce 100,count='+str(count)

con.release()
time.sleep(1)

class Customer(threading.Thread):
def run(self):
global count
while True:
if con.acquire():
if count>100:
count=count-100
print self.name+ 'consume 100, count='+str(count)
else:
con.wait()
con.release()
time.sleep(1)

count=500
con=threading.Condition()

def test():
for i in range(5):
p=Producer()
p.start()
c=Customer()
c.start()
print i


if __name__=='__main__':
test()
python中預設全域變數在函數中可以讀,但是不能寫但是
對con唯讀,所以不用global引入"""
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.