在循环中锁定python中的变量

2024-05-16 01:52:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用Python实现生产者-消费者场景。。。 如果队列已满,生产者应该停止锁定变量,如果队列未满,则释放它。。。我在循环中使用lock变量

def run(self):
        #mutexProducer.acquire()
        #Entering Critical section
        #print self.queue.qsize()
        while True:
            customer=Customer()
            self.mutex.acquire()# acquire condition variable to see if queue is full
            if self.queue.full():
                print "Queue is full : Cant Enter Critical Section"
                #print "Customer %d is discarded" %(customer.id)
            elif not self.queue.full() :
                print "i am here"
                print self.mutex.release()
                self.mutex.acquire()
                #Critical Section
                self.queue.put(customer)#pushing Customer to queue
                print "Customer %d Enters the Queue with %d service " %(customer.id,customer.serviceTime)
                #critical Section
                self.mutex.release()

我的代码一遍又一遍地锁定多个实例吗??我问的原因是我对线程还不熟悉,当队列满了之后,生产者停止创建任何进程(在我的例子中是客户)


Tags: toselfif队列queueissectioncustomer
2条回答

我在你的代码中添加了一些注释,这有一些问题:

def run(self):
        while True:
            customer=Customer()
            self.mutex.acquire()

            if self.queue.full():
                print "Queue is full : Cant Enter Critical Section"
                # NOTE 1: you have to release mutex here: self.mutex.release()
            elif not self.queue.full():
                # NOTE 2: other threads can enter after releasing the lock
                print self.mutex.release()

                self.mutex.acquire()
                #Critical Section
                self.queue.put(customer)
                print "Customer %d Enters the Queue with %d service " %(
                    customer.id,customer.serviceTime
                )
                self.mutex.release()

除了注1之外(但动机相同):

def run(self):
        while True:
            customer=Customer()
            self.mutex.acquire()

            if self.queue.full():
                print "Queue is full : Cant Enter Critical Section"

            elif not self.queue.full():
                # NOTE 2: other threads can enter after releasing the lock
                print self.mutex.release()

                self.mutex.acquire()
                #Critical Section
                self.queue.put(customer)
                print "Customer %d Enters the Queue with %d service " %(
                    customer.id,customer.serviceTime
                )
            # Note 1 alternative - release mutex (cancel 'if' branching effect)
            self.mutex.release()

我真的不明白这是逻辑。您释放了锁,允许线程检查队列,而其他线程推送到队列,但您认为队列不是线程安全的。

如果使用的是队列的线程安全性,那么为什么首先使用互斥锁?

编辑:主要问题是,正如指定的那样,您要与生产者获取两次互斥量。只能获取互斥对象一次(至少当它是threading.Lock对象时)。在您的对讲机中尝试以下代码:

>>> import threading
>>> lock = threading.Lock()
>>> lock.acquire()
True
>>> lock.acquire()

看看会发生什么。

不管怎样,找出关键部分的逻辑。固定代码(注意1)应该可以防止由于在第一个if分支上没有释放互斥锁而导致的阻塞。

祝你好运。

使用Lock的最佳方法是使用with语句。它自动处理锁的获取和释放,即使块因异常而退出。

例如:

lock = threading.Lock()
with lock:
    print "the lock is locked for the duration of this block"
try:
    with lock:
        raise Exception("block exits with an exception")
except Exception:
    pass
assert not lock.locked()

如果不进行新的小修改,就不可能将with语句替换到代码中。但是,这通常反映了应该如何使用锁。

def run(self):
    while True:
        customer=Customer()
        # enter critical section
        with self.mutex:
            queue_full = self.queue.full()
        # exit critical section
        if queue_full:
            print "Queue is full : Cant Enter Critical Section"
        else:
            print "i am here"
            # enter critical section
            with self.mutex:
                #pushing Customer to queue
                self.queue.put(customer)
            # exit critical section
            print "Customer %d Enters the Queue with %d service " % \
                (customer.id, customer.serviceTime)

但是,由于有多个相关的关键部分,如果有多个生产者线程,就会出现问题。如果一个线程检查队列的状态,退出其关键部分,挂起以支持另一个线程,并且在恢复执行时队列已满,会发生什么情况。在前面的关键部分中检查的条件不再适用。因此,所有相关的行动必须在同一个关键部分一起完成。如果只有一个生产者,那么这就不是问题。

应对多个生产商:

def run(self):
    while True:
        customer=Customer()
        if not self.add_customer(customer):
            print "Queue is full: failed to add customer"

def add_customer(self):
    with self.mutex:
        # entire section that checks if the queue is full and then adding the 
        # customer is considered critical
        if not self.queue.full():
            self.queue.put(customer)
            return True # customer added
    return False # customer not added

查看了您的注释中提供的代码here。我可以看出你没有正确使用锁。每个协调线程必须具有对同一锁的访问权限,而不是为每个线程创建新的单独锁。

你的主要方法应该是:

def main():
    queue_size=2
    queue=Queue.Queue(maxsize=queue_size)
    print queue.full()

    # scrap the following three lines
    mutexProducer=threading.Lock()#mutex variablaes
    mutexConsumer=thread.allocate_lock()
    mutexTeller=thread.allocate_lock()

    mutex = threading.Lock()
    # producer and scheduler use the same lock
    producer = Producer(queue, mutex)
    scheduler = Scheduler(queue, mutex)

    producer.start()
    scheduler.start()

相关问题 更多 >