What is the Global VM Lock and how does it affect concurrency?
MRI, the standard Ruby implementation, has a Global VM Lock: only one thread executes Ruby bytecode at a time, so threads do not provide CPU parallelism for pure Ruby code. They do improve concurrency for I/O because the lock is released around blocking operations such as file, socket and database calls.
threads = urls.map do |url|
Thread.new { fetch(url) } # overlaps I/O, not CPU
end
results = threads.map(&:value)
For CPU-bound work you need process-level parallelism: fork, the Process API, multiple server workers under Puma or Unicorn, or a different implementation such as JRuby or TruffleRuby, which have no GVL.
Since Ruby 3.0 the lock is more granular, and Ractors offer actor-style parallelism in limited cases. Concurrency primitives include Mutex, ConditionVariable and Queue. Choose processes for parallelism and threads for overlapping I/O.