What if your program's data got scrambled just because two parts tried to change it at once?
Why Thread synchronization with Mutex in Ruby? - Purpose & Use Cases
Imagine you and your friends are all trying to write on the same notebook at the same time. Without any order, your writings get mixed up and messy.
When multiple threads try to change the same data without control, they overwrite each other's work. This causes bugs that are hard to find and fix, making the program unreliable.
A Mutex acts like a lock on the notebook. Only one friend can write at a time, so the notes stay neat and correct. This keeps the program safe and predictable.
counter = 0 threads = 10.times.map do Thread.new { counter += 1 } end threads.each(&:join) puts counter
counter = 0 mutex = Mutex.new threads = 10.times.map do Thread.new do mutex.synchronize { counter += 1 } end end threads.each(&:join) puts counter
It lets multiple threads work together safely without messing up shared data.
In a bank system, many users withdraw or deposit money at the same time. Mutex ensures the account balance updates correctly without errors.
Without control, threads can cause data chaos.
Mutex locks let only one thread change data at a time.
This keeps programs safe, reliable, and easier to understand.
Practice
Mutex in Ruby threads?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 BQuick Check:
Mutex protects shared data = prevent simultaneous access [OK]
- Thinking Mutex speeds up threads
- Believing Mutex creates threads
- Assuming Mutex stops threads completely
Solution
Step 1: Recall Mutex usage in Ruby
Ruby's Mutex class provides asynchronizemethod to wrap critical code safely.Step 2: Compare options
Onlymutex.synchronize { critical_code }is the correct and safe syntax.Final Answer:
mutex.synchronize { critical_code } -> Option AQuick Check:
Use synchronize method to protect code [OK]
- Forgetting to unlock mutex after lock
- Using non-existent methods like run or start
- Not wrapping critical code in a block
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 counterSolution
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 CQuick Check:
3 threads * 2 increments each = 6 [OK]
- Ignoring mutex and expecting wrong count
- Counting only one thread's increments
- Confusing thread join effect
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 counterSolution
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, callmutex.unlockor better usemutex.synchronizeto auto-handle locking/unlocking.Final Answer:
Missing mutex.unlock causes deadlock; fix by adding mutex.unlock after increment -> Option DQuick Check:
Always unlock mutex after lock to avoid deadlock [OK]
- Forgetting to unlock mutex
- Removing mutex when needed
- Initializing shared data inside threads incorrectly
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.sizeSolution
Step 1: Understand thread safety for shared hash
Multiple threads writing to shared_hash need protection to avoid data corruption.Step 2: Use mutex.synchronize for safe updates
mutex.synchronize { shared_hash[i * 10 + j] = "value" } wraps the update insidemutex.synchronize, ensuring only one thread writes at a time.Final Answer:
mutex.synchronize { shared_hash[i * 10 + j] = "value" } -> Option AQuick Check:
Use synchronize block to protect shared hash updates [OK]
- Updating shared hash without mutex
- Locking mutex without unlocking
- Using Thread.pass instead of mutex
Ready to prove it?
Pass the test and this pattern moves unknown
