gpt4 book ai didi

ruby - 生产者/消费者的特例

转载 作者:数据小太阳 更新时间:2023-10-29 08:05:54 25 4
gpt4 key购买 nike

我正在尝试同步一种特殊的生产者/消费者问题。这是问题所在:

我有 2 个队列 link_queue, page_queue

线程class ProducePages_RequireLinks(称之为class A),顾名思义,使用link_queue中的项目并放入任意数量的( >=1) 来自每个链接的页面进入 page_queue

相反,主线程 class ProduceLinks_RequirePages(称之为 class B)使用 page_queue 中的页面并入队任意数量(>= 0) 链接到 link_queue

现在 class B 生成链接的速度可能比 class A 生成页面的速度快。另一方面,反过来也是可能的。

如何在 Ruby 1.9.2 中正确同步这些线程?

我尝试在两者中都使用监视器,但在某些时候我最终遇到了死锁。

(如果我不准确,请通过评论告诉我,我会发布一些示例类)


编辑:正在发生的事情的图片:

enter image description here

例子

link_queue 初始化为 1 个项目page_queue 初始化为 0 个项目

我们有 4 个 A 类线程 和 1 个 B 类线程。每行将是 1 个时间步。


线程 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 下降到某个阈值以下。否则我们会在某个时候耗尽内存。

干杯

最佳答案

无论您使用的是 Ruby 还是任何其他语言,只要您拥有此处描述的生产者-消费者设计,无论生产者和消费者是线程还是进程,您都必须永远不要假设消费者能够“跟上”生产者的步伐。您必须始终使用有界队列。即使像您在评论中提到的那样使用外部队列在一般情况下也不能解决问题,因为虽然比 RAM 大得多,但外部存储不是无限的。

Ruby 标准库有 SizedQueue,您可以通过 require 'thread' 获得它。 SizedQueue 是一个线程安全的队列,它的大小是有限的。如果生产者线程试图在队列已满时将项目插入队列,则生产者将阻塞,直到消费者从队列中弹出一个项目(为新项目腾出空间)。这将给消费者一个“追赶”的机会。同样,如果消费者线程试图在队列为空时从队列中弹出一个项目,则消费者将阻塞直到有项目可用。

如果总体吞吐量受到生产者的限制,他们往往会获得更多的 CPU 时间(因为消费者会阻塞)。另一方面,如果消费者是瓶颈,他们往往会获得更多的 CPU 时间。这比让生产者消耗系统资源用不断增长的项目填充您的队列要好,而消费者可以使用这些资源来处理积压。

关于ruby - 生产者/消费者的特例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7265504/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com