生产者/消费者的特例

3
我正在尝试同步一种特殊的生产者/消费者问题。 这是问题:
我有2个队列link_queue,page_queue。
线程类ProducePages_RequireLinks(称为class A),如其名称所示,从link_queue中消耗项目,并将每个链接的任意数量(≥1)的页面放入page_queue中。
相反,主线程ProduceLinks_RequirePages(称为class B)从page_queue中消耗页面,并将任意数量(≥0)的链接排队到link_queue中。
现在可能会出现class B比class A生成链接更快的情况。另一方面,反过来也可能发生。
如何在Ruby 1.9.2中正确同步这些线程?
我尝试在两者中都使用监视器,但在某些时候我最终陷入死锁。
(如果我没有准确,请通过评论告诉我,我会发布一些示例类)
编辑: 正在进行的图片: link_queue初始化为1项 page_queue初始化为0项
我们有4个class A线程和1个class B线程。每行都是一个时间步长。
线程A.1抓取1个链接(linkQ = 0),输出1个页面(pageQ = 1)
线程B抓取1页(pageQ = 0),输出400个链接(linkQ = 400)
线程A.3抓取1个链接(linkQ = 399),输出1个页面(pageQ = 1)
线程A.2抓取1个链接(linkQ = 398),输出1个页面(pageQ = 2)
线程B抓取1页(pageQ = 1),输出100个链接(linkQ = 498)
线程A.1抓取1个链接(linkQ = 497),输出1个页面(pageQ = 2)
线程A.4抓取1个链接(linkQ = 496),输出1个页面(pageQ = 3)
线程B注意到linkQ太大,等待直到linkQ <16
…线程A.*继续工作…之后(linkQ = 15)和(pageQ = 484)
现在我们有相反的问题。现在,线程A必须等待,直到pageQ下降到某个阈值以下。否则,我们最终会耗尽内存。

干杯!


队列大小是否固定?如果是,这个问题可能根本无法解决。 - templatetypedef
好的,就可用内存而言,它们是“固定的”。所以我想是的。我的方法是限制项目数量,并让每个线程等待,直到其他线程处理了足够的数据。反之亦然。这是一个鸡生蛋的问题。循环等待。 - pokey909
我会在我的问题中举一些例子... - pokey909
有没有办法限制在处理每个列表条目时产生的元素数量? - templatetypedef
是的,每个链接都会生成1个页面。但是每个页面可能会生成任意数量的链接。 - pokey909
显示剩余4条评论
2个回答

2
无论你使用Ruby还是其他任何语言,只要你有像你在这里描述的生产者-消费者设计,无论生产者和消费者是线程还是进程,你都不能假设消费者能够跟上生产者的速度。你必须始终使用有限队列。即使像你在评论中提到的使用外部队列,在一般情况下也无法解决问题,因为虽然比RAM大得多,但外部存储并不是无限的。
Ruby标准库中有SizedQueue,可以通过require 'thread'获得。SizedQueue是一个线程安全的队列,其大小是有限制的。如果生产线程尝试将项目推入已满的队列时,生产者将被阻塞,直到消费者弹出一个项目(为新项目腾出空间)。这将给消费者们一个赶上来的机会。同样地,如果消费线程尝试从空队列中弹出项目,则消费者将被阻塞,直到项目可用。
如果整体吞吐量受生产者限制,它们倾向于获得更多的CPU时间(因为消费者被阻塞)。另一方面,如果消费者是瓶颈,它们将倾向于获得更多的CPU时间。这比允许生产者耗尽系统资源填充队列中不断增长的项目,而消费者可以利用这些资源来处理积压的任务更好。

0

根据你所说的,似乎你有反馈循环问题。因此,在回答问题同步部分之前,我必须问一下你的问题范围是什么?

如果你正在构建一个尝试枚举互联网上每个页面的网络爬虫系统,那么无论如何进行线程同步都无法将其放入RAM中。

那么循环呢?页面a链接到页面b和c,页面b链接到页面a和c,等等?根据你描述的问题,每次迭代都会指数级增长队列。如果要处理的页面数量是有限的,那么它有多大?如果你一遍又一遍地遍历某些页面,是否应该基于最近已经处理过的原则跳过页面?

总之,为了解决这个问题,你必须确保平均每个周期产生另一个新周期,通过某些链接产生零个页面而不是一个页面,以及页面产生0个链接。

或者,你想做什么?其他方法可能更合适。


一般来说,你是正确的,这个反馈系统是不稳定的,因为平均每个页面生成的链接数量大于1,导致内存消耗会趋向于无限。我认为没有办法通过限制一个线程来让另一个线程追赶来解决这个问题。我的当前解决方案是使用外部队列来存储数据,这个方法运行得很好。感谢你的帮助。 - pokey909

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接