Mutex

Work In Progress

Mutex (MUTual EXclusion) is a way to ensure only lock holder can use CPU. Others need to block and wait off-CPU. E.g., Multiple threads try to access shared array. You can use Mutex to protect a piece of work in multi-threaded world. Mutex make sure only one thread at any given time can access this code. Mutex can be implemented by library or Kernel.

mutex = Mutex.new
mutex.synchronize do
  # guarantee only 1 thread can access this block
  user.withdraw! 500
end

Unlike Monitor, you cannot have nested synchronize block with Mutex.

Obtain/Release lock

mutex = Mutex.new
mutex.lock

You can also use #try_lock and returns false when this mutex is locked by another thread. There is also a #locked? method to check if a mutex has been locked or not. After you finished using the mutex, release it by: mutex.unlock.

Trying to lock a locked mutex:

mutex = Mutex.new
mutex.lock

mutex.lock
ThreadError: deadlock; recursive locking

Trying to unlock a not locked mutex:

mutex = Mutex.new

mutex.unlock
ThreadError: Attempt to unlock a mutex which is not locked

and you can’t unlock the mutex in another thread:

mutex = Mutex.new
mutex.lock

Thread.new { mutex.unlock }.join
#<Thread:0x00007f8407b480b0 (pry):3 run> terminated with exception (report_on_exception is true):
(pry):12:in `unlock': Attempt to unlock a mutex which is locked by another thread/fiber (ThreadError)

I believe this

mutex.synchronize do
  # ...
end

equals to

mutex = Mutex.new
begin
  mutex.lock
  # ...
ensure
  mutex.unlock
end

Thread::ConditionVariable

Put thread(s) to sleep until certain condition and wake up threads when condition satisfies. Usually use together with Mutex. When a thread sleep, another thread can do work, and with the condition variable, we can avoid hot loop.

mutex = Mutex.new
resource = ConditionVariable.new
thread_a = Thread.new do
  mutex.synchronize do
    # Thread A needs the resource
    resource.wait(mutex)
    # Thread A can have the resource
  end
end
thread_b = Thread.new do
  mutex.synchronize do
    # Thread B finished using the resource
    resource.signal
  end
end

Real-world example:

APIs: wait(mutex, timeout = nil) (stop current thread, release the lock of Mutex), signal (wake up a single thread that was waiting for the lock of Mutex), broadcast (wake up all threads that were waiting for the lock of Mutex)

ConditionVariable is an alias of Thread::ConditionVariable.

Learn More

Generic Mutex Subsystem — Linux Kernel’s document about Mutex.