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引入"""