Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing an enumerator across threads

I want to call a common enumerator from different threads. When I do the following,

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

it raises an error:

Fiber called across threads.

when enum is called from t2 after once being called from t1.

  • Why is Ruby designed to not allow an enumerator (or fiber) to be called across threads, and
  • Is there an alternative way to provide a similar function?

I am guessing that atomicity of an operation on an enumerator/fiber is relevant here, but am not fully sure. If that is the issue, then exclusively-locking the enumerator/fiber while in use shall solve the problem, and I don't know why calling an enumerator/fiber across threads is prohibited in general. If an alternative can be provided by using locking, that would satisfy my need.

like image 338
sawa Avatar asked Feb 23 '14 09:02

sawa


People also ask

Is enumeration thread-safe?

Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads could still modify the collection, which causes the enumerator to throw an exception.

Can we run two threads simultaneously?

Within a process or program, we can run multiple threads concurrently to improve the performance. Threads, unlike heavyweight process, are lightweight and run inside a single process – they share the same address space, the resources allocated and the environment of that process.

How to make collection thread-safe in c#?

Bounding and blocking functionality for any type. Thread-safe implementation of a dictionary of key-value pairs. Thread-safe implementation of a FIFO (first-in, first-out) queue. Thread-safe implementation of a LIFO (last-in, first-out) stack.

Is collection thread-safe c#?

CSharp Online Training Concurrent namespace. The namespace has numerous collection classes. These classes are both thread-safe and scalable.


Video Answer


1 Answers

You can use 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
like image 90
Uri Agassi Avatar answered Oct 16 '22 08:10

Uri Agassi