d(%s) released, Number: %d'%(self.t_name, num) break num+=1 print 'Thread(%s) released, Number: %d'%(self.t_name, num) mylock.release() def test():thread1 = myThread('A') thread2 = myThread('B') thread1.start() thread2.start() if __name__== '__main__':test() 我们把修改共享数据的代码成为“临界区”。必须将所有“临界区”都封闭在同一个锁对象的acquire和release之间。 2、 条件同步锁只能提供最基本的同步。假如只在发生某些事件时才访问一个“临界区”,这时需要使用条件变量Condition. Condition对象是对Lock对象的包装,在创建Condition对象时,其构造函数需要一个Lock对象作为参数,如果没有这个Lock对象参数,Condition将在内部自行创建一个Rlock对象。在Condition对象上,当然也可以调用acquire和release操作,因为内部的Lock对象本身就支持这些操作。但是Condition的价值在于其提供的wait和notify的语义。 条件变量是如何工作的呢?首先一个线程成功获得一个条件变量后,调用此条件变量的wait()方法会导致这个线程释放这个锁,并进入“blocked”状态,直到另一个线程调用同一个条件变量的notify()方法来唤醒那个进入“blocked”状态的线程。如果调用这个条件变量的notifyAll()方法的话就会唤醒所有的在等待的线程。 如果
程序或者线程永远处于“blocked”状态的话,就会发生死锁。所以如果使用了锁、条件变量等同步机制的话,一定要注意仔细检查,防止死锁情况的发生。对于可能产生异常的临界区要使用异常处理机制中的finally子句来保证释放锁。等待一个条件变量的线程必须用notify()方法显式的唤醒,否则就永远沉默。保证每一个wait()方法调用都有一个相对应的notify()调用,当然也可以调用notifyAll()方法以防万一。 生产者与消费者问题是典型的同步问题。这里简单介绍两种不同的实现方法。 1, 条件变量 view plaincopy to clipboardprint? import threading import time class Producer(threading.Thread): def __init__(self, t_name): threading.Thread.__init__(self, name=t_name) def run(self): global x con.acquire() if x > 0: con.wait() else: for i in range(5): x=x+1 print "producing……" + str(x) con.notify() print x con.release() class Consumer(threading.Thread): def __init__(self, t_name): threading.Thread.__init__(self, name=t_name) def run(self): global x con.acquire() if x == 0: print 'consumer wait1' con.wait() else: for i in range(5): x=x-1 print "consuming……" + str(x) con.notify() print x con.release() con = threading.Condition() x=0 print 'start consumer' c=Consumer('consumer') print 'start producer' p=Producer('producer') p.start() c.start() p.join() c.join() print x 上面的例子中,在初始状态下,Consumer处于wait状态,Producer连续生产(对x执行增1操作)5次后,notify正在等待的Consumer.Consumer被唤醒开始消费(对x执行减1操作) 2, 同步队列Python中的Queue对象也提供了对线