Правильное использование Mutex / Хороший стиль кодирования? - PullRequest
1 голос
/ 20 декабря 2010

В следующем коде производитель periodically_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

Это «хороший» стиль кодирования или есть более элегантные подходы?

Спасибо!

1 Ответ

1 голос
/ 20 декабря 2010

Не с этим дизайном.Некоторые альтернативные конструкции могут выполнять одну из следующих задач, но, естественно, имеют свою собственную банку с червями.

«Вилка»

Для каждой работы вы запускаете новый поток или процесс, давая ему работу

Делегирование

Делегирование задачи в очередь в каждом потоке.Каждый поток извлекает из своей собственной уникальной очереди.

Stride

У вас есть кольцевой буфер, и каждый поток проверяет с различным интервалом.EG Num_threads + thread.id Это, вероятно, не для вашей ситуации.

Диапазон

Поток отвечает за ряд заданий.num_threads * thread.id Это, вероятно, не для вашей ситуации.

...