Always use mutex.synchronize to wrap code that changes shared data.
Without mutex, threads can overwrite each other's changes, causing wrong results.
Mutex only locks one thread at a time; others wait patiently.
Summary
Mutex helps threads work together without breaking shared data.
Use mutex.synchronize to protect critical code sections.
Thread synchronization avoids bugs from simultaneous changes.
Practice
(1/5)
1. What is the main purpose of using a Mutex in Ruby threads?
easy
A. To create new threads automatically
B. To prevent multiple threads from accessing shared data at the same time
C. To speed up thread execution by running them in parallel
D. To stop threads from running
Solution
Step 1: Understand what shared data means in threads
Shared data is information that multiple threads can access or change.
Step 2: Identify the role of Mutex
Mutex ensures only one thread changes shared data at a time to avoid errors.
Final Answer:
To prevent multiple threads from accessing shared data at the same time -> Option B
Quick Check:
Mutex protects shared data = prevent simultaneous access [OK]
Hint: Mutex locks shared data to avoid conflicts between threads [OK]
Common Mistakes:
Thinking Mutex speeds up threads
Believing Mutex creates threads
Assuming Mutex stops threads completely
2. Which of the following is the correct way to use a Mutex to protect a critical section in Ruby?
easy
A. mutex.synchronize { critical_code }
B. mutex.lock; critical_code
C. mutex.run(critical_code)
D. mutex.start { critical_code }
Solution
Step 1: Recall Mutex usage in Ruby
Ruby's Mutex class provides a synchronize method to wrap critical code safely.
Step 2: Compare options
Only mutex.synchronize { critical_code } is the correct and safe syntax.
Final Answer:
mutex.synchronize { critical_code } -> Option A
Quick Check:
Use synchronize method to protect code [OK]
Hint: Use mutex.synchronize { } to wrap critical code [OK]
Common Mistakes:
Forgetting to unlock mutex after lock
Using non-existent methods like run or start
Not wrapping critical code in a block
3. What will be the output of this Ruby code?
require 'thread'
mutex = Mutex.new
counter = 0
threads = 3.times.map do
Thread.new do
2.times do
mutex.synchronize { counter += 1 }
end
end
end
threads.each(&:join)
puts counter
medium
A. 2
B. 3
C. 6
D. 0
Solution
Step 1: Count total increments
There are 3 threads, each increments counter 2 times, total 3*2=6 increments.
Step 2: Understand mutex effect
Mutex ensures increments happen safely without losing counts, so final counter is 6.
Final Answer:
6 -> Option C
Quick Check:
3 threads * 2 increments each = 6 [OK]
Hint: Multiply threads by increments inside synchronize block [OK]
Common Mistakes:
Ignoring mutex and expecting wrong count
Counting only one thread's increments
Confusing thread join effect
4. Identify the problem in this Ruby code using Mutex and how to fix it:
require 'thread'
mutex = Mutex.new
counter = 0
threads = 2.times.map do
Thread.new do
mutex.lock
counter += 1
end
end
threads.each(&:join)
puts counter
medium
A. Threads are not joined properly; fix by joining inside the thread block
B. Mutex is not needed here; remove mutex.lock
C. counter should be initialized inside the thread
D. Missing mutex.unlock causes deadlock; fix by adding mutex.unlock after increment
Solution
Step 1: Check mutex usage
Mutex is locked but never unlocked, causing threads to wait forever (deadlock).
Step 2: Fix by unlocking mutex
After increment, call mutex.unlock or better use mutex.synchronize to auto-handle locking/unlocking.
Final Answer:
Missing mutex.unlock causes deadlock; fix by adding mutex.unlock after increment -> Option D
Quick Check:
Always unlock mutex after lock to avoid deadlock [OK]
Hint: Always unlock mutex or use synchronize block [OK]
Common Mistakes:
Forgetting to unlock mutex
Removing mutex when needed
Initializing shared data inside threads incorrectly
5. You want to safely update a shared hash from multiple threads in Ruby. Which approach correctly uses Mutex to avoid race conditions?
shared_hash = {}
mutex = Mutex.new
threads = 5.times.map do |i|
Thread.new do
10.times do |j|
# What goes here?
end
end
end
threads.each(&:join)
puts shared_hash.size