The lock and its name

Free preview 4 min to read

Two engineers are looking at the same graph. Puma runs sixteen threads, the box has eight cores, and CPU sits at 12% while p95 latency climbs. One says "the GIL is the problem". The other says "we aren't even CPU-bound, add threads". Both are arguing about a lock neither of them has ever measured.

That lock has a name, and the first thing to get right is which one. In CRuby the mechanism is called the Global VM Lock, or GVL. You'll also hear GIL, for Global Interpreter Lock. That's the Python term, and it was Ruby's own older name for the same thing. Both refer to the same lock. GVL is what MRI's own C API uses, in function names like rb_thread_call_without_gvl, and it's the name this course uses from here on.

The naming matters slightly more than pedantry, because "VM lock" says the useful thing and "interpreter lock" doesn't. The lock guards the virtual machine's own state. It doesn't guard yours.

What you already believe, and why it isn't enough

The senior course "Ruby: concurrency" opened with a measurement: threads summing squares took as long as doing the same work one piece after another. It named the cause, a global lock, and deliberately stopped there, because the consequence was all you needed to choose a model.

You're past choosing now. The consequence alone can't answer the questions that come up during a production incident:

  • Why do threads help a database-heavy endpoint but not a template-heavy one?
  • If one thread runs at a time, why is my counter still wrong?
  • How many Puma threads are right for this app specifically, instead of in general?
  • Am I even GVL-bound right now, or am I guessing?

Every one of those has a real answer. None of them is reachable from "only one thread runs Ruby at a time".

The shape of the mechanism

Picture the interpreter as a single room with one key. A thread can't execute Ruby bytecode without holding the key. It gives the key up in two situations: when it's about to wait for something outside Ruby, and when the VM's timer taps it on the shoulder because it has held the key long enough.

thread A  [--ruby--]        [--ruby--]
thread B            [--ruby--]        [--ruby--]
                    ^                 ^
                    |                 |
              A blocked on I/O   timer preempted A

Two release points have completely different consequences. The I/O release is why threaded web servers work at all. The timer release is why your unsynchronized counter can be wrong.

What this course covers

Lesson 2 opens the room up. It covers which pieces of interpreter state the lock protects, why the object allocation path and the garbage collector are on that list, and why your @balance isn't.

Lesson 3 is the consequence engineers get wrong most often. The GVL doesn't make your code thread-safe, and you'll watch a counter lose most of its increments to prove it. That lesson carries the coding challenge.

Lesson 4 is the release around blocking work: sleeping, reading a socket, and C extensions that hand the key back on purpose with rb_thread_call_without_gvl. This mechanism is behind the claim that threads help I/O.

Lesson 5 is the switching model: preemption on a timer, measured here at roughly 100 ms, Thread.pass, and what the M:N scheduler introduced in Ruby 3.3 does and doesn't change.

Lesson 6 is the skill the rest exists to support: measuring. It compares wall time with CPU time and sequential runs with threaded ones, and shows how to read the two numbers together.

Lesson 7 walks into a Rails process, sets Puma's thread count against the GVL and asks where Ractors leave all of this.

Start with the room and the key. Almost every wrong belief about the GVL comes from assuming it protects something it never touched.

Lesson 1 of 7 · free

Keep going with lesson 2

What the lock actually protects

Lists the VM state the GVL protects, including allocation and the garbage collector, and where that guarantee stops.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...