正确的互斥使用/良好的编码风格?

发布于 2024-10-08 04:11:13 字数 1549 浏览 1 评论 0原文

在下面的代码中,生产者periodic_fill_page_queue可能会向当前正在使用的队列添加一个页面(阅读:在设置状态being_processed之前在消费者中)。

class Example

  def initialize
    @threads      = ThreadGroup.new
    @page_queue   = Queue.new
    Thread.abort_on_exception = true
  end

  def start
    periodically_fill_page_queue
    periodically_process_page_queue
  end

  def periodically_fill_page_queue
    @threads.add(Thread.new do
      loop do
        if @page_queue.empty?
          Page.with_state(:waiting).each do |p|
            p.queued!
            @page_queue << f
          end
        end
        sleep 2
      end
    end)
  end

  def periodically_process_page_queue
    loop do
      until file = @page_queue.pop
        sleep 2
      end
      page.being_processed
      process(page)
    end
  end

  def process(page)
    sleep 120
    page.processed
  end

end


class Page < ActiveRecord::Base

  state_machine :state, :initial => :waiting do

    event :queued do
      transition :waiting => :queued
    end

    event :being_processed do
      transition :queued => :being_processed
    end

    event :processed do
      transition :being_processed => :processed
    end

  end

end

为了避免这种情况,我会使用 Mutex 对象:

def initialize
  ...
  @mutex = Mutex.new
end

def periodically_process_page_queue
  loop do
    until file = @page_queue.pop
      sleep 2
    end
    @mutex.synchronize { page.being_processed }
    process(page)
  end
end

这是“好的”编码风格,还是有更优雅的方法?

谢谢!

Within the following code, the producer periodically_fill_page_queue might add a page to the queue that is currently being consumed (read: in the consumer before the status being_processed is set).

class Example

  def initialize
    @threads      = ThreadGroup.new
    @page_queue   = Queue.new
    Thread.abort_on_exception = true
  end

  def start
    periodically_fill_page_queue
    periodically_process_page_queue
  end

  def periodically_fill_page_queue
    @threads.add(Thread.new do
      loop do
        if @page_queue.empty?
          Page.with_state(:waiting).each do |p|
            p.queued!
            @page_queue << f
          end
        end
        sleep 2
      end
    end)
  end

  def periodically_process_page_queue
    loop do
      until file = @page_queue.pop
        sleep 2
      end
      page.being_processed
      process(page)
    end
  end

  def process(page)
    sleep 120
    page.processed
  end

end


class Page < ActiveRecord::Base

  state_machine :state, :initial => :waiting do

    event :queued do
      transition :waiting => :queued
    end

    event :being_processed do
      transition :queued => :being_processed
    end

    event :processed do
      transition :being_processed => :processed
    end

  end

end

To avoid this, i'd use a Mutex object:

def initialize
  ...
  @mutex = Mutex.new
end

def periodically_process_page_queue
  loop do
    until file = @page_queue.pop
      sleep 2
    end
    @mutex.synchronize { page.being_processed }
    process(page)
  end
end

Is this "good" coding style, or are there any more elegant approaches?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

罪歌 2024-10-15 04:11:13

不是这个设计。一些替代设计可能会执行以下操作之一,但自然也有自己的麻烦。

“分叉”

对于每个作业,您启动一​​个新线程或进程,将作业

委托

给它,将任务委托给每个线程中的队列。每个线程都从自己独特的队列中拉取。

Stride

您有一个循环缓冲区,每个线程以不同的时间间隔进行检查。 EG Num_threads + thread.id
这可能不适合你的情况。

范围

线程负责一系列作业。 num_threads * thread.id
这可能不适合你的情况。

Not with this design. Some alternative designs might do one of the below, but naturally have their own can of worms.

"Fork"

For each job you start a new thread or process, giving it the job

Delegation

Delegate the task to a queue in each thread. Each thread pulls from its own unique queue.

Stride

You have a circular buffer and each thread checks at a different interval. E.G. Num_threads + thread.id
This probably isn't for your situation.

Range

A thread is responsible for a range of jobs. num_threads * thread.id
This probably isn't for your situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文