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.

mutex = Mutex.new
mutex.lock
mutex.unlock

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

which means other threads need to wait the current thread executes the code in synchronize block.

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.

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