Совместное использование перечислителя между потоками

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

enum = (0..1000).to_enum
t1 = Thread.new do
  p enum.next
  sleep(1)
end
t2 = Thread.new do
  p enum.next
  sleep(1)
end
t1.join
t2.join

это вызывает ошибку:

Fiber called across threads.

когда enum вызывается из t2 после того, как однажды позвонили из t1,

  • Почему Ruby не позволяет вызывать перечислитель (или волокно) между потоками, и
  • Есть ли альтернативный способ предоставить аналогичную функцию?

Я предполагаю, что атомарность операции на счетчике / волокне имеет отношение здесь, но я не совсем уверен. Если это проблема, то исключительная блокировка перечислителя / оптоволокна во время использования должна решить проблему, и я не знаю, почему вызов перечислителя / оптоволокна через потоки вообще запрещен. Если альтернатива может быть предоставлена ​​с помощью блокировки, это удовлетворит мою потребность.

1 ответ

Ты можешь использовать Queue

queue = Queue.new
(0..1000).map(&queue.method(:push))

t1 = Thread.new do
  while !queue.empty?
    p queue.pop(true)
    sleep(0.1)
  end
end
t2 = Thread.new do
  while !queue.empty?
    p queue.pop(true)
    sleep(0.1)
  end
end
t1.join
t2.join
Другие вопросы по тегам