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()
"""
示範條件變數同步的經典問題是生產者與消費者問題:假設有一群生產者(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引入"""