Threads and fibers

Threads

A thread runs a block alongside your main program. The main program keeps going immediately — nothing waits unless you ask it to. Call join when you need the result before continuing:

worker = Thread.new do puts "hello from a thread" end worker.join puts "done"

hello from a thread
done

Without join the program could exit before the thread prints anything. Read the computed value with value instead — it joins implicitly and returns whatever the block evaluated to.

The GVL

CRuby runs threads on top of the Global VM Lock (GVL, historically called the GIL): only one thread executes Ruby code at a time. Threads still help whenever a thread waits — network responses, files, sleep — because a waiting thread releases the lock for the others.

Pure computation does not get faster with more threads on CRuby: two threads crunching numbers take turns instead of running in parallel. For CPU-bound work use processes (see lesson 163, later) or JRuby/TruffleRuby, which have no GVL.

Fibers

A fiber is cooperative: it runs only when you resume it and pauses only where it yields. No surprises, no races — you control every switch:

fiber = Fiber.new do Fiber.yield 1 Fiber.yield 2 end puts fiber.resume puts fiber.resume

1
2

Mutex

Threads share all variables, so two threads appending at once can corrupt an array. A mutex lets only one thread inside the critical section at a time. Collect the squares of 0, 1, 2 safely and print them sorted:

results = [] mutex = Mutex.new workers = 3.times.map do |i| Thread.new do square = i * i mutex.synchronize { results << square } end end workers.each(&:join) puts results.sort.inspect

[0, 1, 4]

Rule of thumb: share as little as possible, guard what you share with a mutex, and join every thread you start.

Article author: Arthur Isaev