python - 线程 - 具有 Counter 对象的生产者/消费者
问题描述
我在下面编写了一个代码片段,旨在实现以下目标。我有一个在所有消费者之间共享的计数器对象,这些消费者在完成他们的任务后,递增计数器并耐心等待。这个想法是创建一个新的 IP 地址,然后其他线程可以在他们的新任务中使用,这将由生产者完成,生产者还检查计数器是否具有某些值,如果是,它将创建一个新的ip 并通知所有人,否则通知所有人而不创建新 ip。但由于某种原因,我从来没有收到过NOT SETTING A NEW IP ADDRESS
消息。有人能告诉我为什么吗?
非常感谢:
import logging
import threading
import time
import random
class Counter(object):
def __init__(self, start=0):
self.lock = threading.RLock()
self.value = start
def increment(self):
logging.debug('Waiting for lock')
with self.lock:
logging.debug('Acquired lock. Current counter value: {}'.format(self.value + 1))
self.value = self.value + 1
def consumer(cond, counter):
"""wait for the condition and use the resource"""
logging.debug('Starting consumer thread')
while True:
time_sleep = random.randint(5, 10) / 5
time.sleep(time_sleep)
with cond:
counter.increment()
logging.debug('Resource is available to consumer. Doing some werk on counter {}'.format(counter.value))
logging.debug('Done some werk. Waiting for other threads to finish their werk and for producer to signal continuation.')
cond.wait()
def producer(cond, counter):
"""set up the resource to be used by the consumer"""
logging.debug('Starting producer thread')
for i in range(4):
logging.debug('Producer sleeping for 3 seconds')
time.sleep(3)
with cond:
if counter.value % 2 == 0:
logging.debug('Setting a new ip address')
cond.notifyAll()
if counter.value % 2 != 0:
logging.debug('NOT SETTING A NEW IP ADDRESS')
cond.notifyAll()
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s (%(threadName)-2s) %(message)s',
)
condition = threading.Condition()
c = Counter()
c1 = threading.Thread(name='c1', target=consumer,
args=(condition, c))
c2 = threading.Thread(name='c2', target=consumer,
args=(condition, c))
p = threading.Thread(name='p', target=producer,
args=(condition, c))
c1.start()
c2.start()
p.start()
解决方案
尝试在生产者线程中添加锁。
其他线程应该等待生产者完成其任务。
这可以防止计数器在生产者线程执行期间被其他线程覆盖。
def producer(cond, counter):
"""set up the resource to be used by the consumer"""
logging.debug('Starting producer thread')
with self.lock
for i in range(4):
logging.debug('Producer sleeping for 3 seconds')
time.sleep(3)
with cond:
if counter.value % 2 == 0:
logging.debug('Setting a new ip address')
cond.notifyAll()
if counter.value % 2 != 0:
logging.debug('NOT SETTING A NEW IP ADDRESS')
cond.notifyAll()
推荐阅读
- redux - Redux 中的 State 是否同时包含 Model 和 ViewModel?
- azure - 基于 alpine 的 Azure Functions v3 docker 镜像
- vue.js - 在 Vuejs 中使用单击事件停止动画?
- sql - 在 Oracle 中合并内部和外部联接的问题
- javascript - 比较两个日期和时间时显示“无效日期”
- reactjs - 更改了上下文存储,但浏览器加载了旧的存储
- sql - Laravel 8 PUT 路由返回 404
- c - 如何在 FUSE 中跟踪工作目录
- r - 如何在 R 中获取 rnorm 数据集的平均值?
- bash - 在 bash 中重定向管道输出