# class Thread::Mutex

`Thread::Mutex` implements a simple semaphore that can be used to coordinate access to shared data from multiple concurrent threads.

Example:

    semaphore = Thread::Mutex.new

    a = Thread.new {
      semaphore.synchronize {
        # access shared resource
      }
    }

    b = Thread.new {
      semaphore.synchronize {
        # access shared resource
      }
    }

### Public Class Methods

Thread::Mutex.new → mutex click to toggle source

Creates a new `Mutex`

    static VALUE
    mutex_initialize(VALUE self)
    {
        return self;
    }

### Public Instance Methods

lock → self click to toggle source

Attempts to grab the lock and waits if it isn’t available. Raises `ThreadError` if `mutex` was locked by the current thread.

    VALUE
    rb_mutex_lock(VALUE self)
    {
        return do_mutex_lock(self, 1);
    }

locked? → true or false click to toggle source

Returns `true` if this lock is currently held by some thread.

    VALUE
    rb_mutex_locked_p(VALUE self)
    {
        rb_mutex_t *mutex = mutex_ptr(self);

        return RBOOL(mutex->fiber);
    }

owned? → true or false click to toggle source

Returns `true` if this lock is currently held by current thread.

    VALUE
    rb_mutex_owned_p(VALUE self)
    {
        rb_fiber_t *fiber = GET_EC()->fiber_ptr;
        rb_mutex_t *mutex = mutex_ptr(self);

        return mutex_owned_p(fiber, mutex);
    }

sleep(timeout = nil) → number or nil click to toggle source

Releases the lock and sleeps `timeout` seconds if it is given and non-nil or forever. Raises `ThreadError` if `mutex` wasn’t locked by the current thread.

When the thread is next woken up, it will attempt to reacquire the lock.

Note that this method can wakeup without explicit `Thread#wakeup` call. For example, receiving signal and so on.

Returns the slept time in seconds if woken up, or `nil` if timed out.

    static VALUE
    mutex_sleep(int argc, VALUE *argv, VALUE self)
    {
        VALUE timeout;

        timeout = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
        return rb_mutex_sleep(self, timeout);
    }

synchronize { ... } → result of the block click to toggle source

Obtains a lock, runs the block, and releases the lock when the block completes. See the example under `Thread::Mutex`.

    static VALUE
    rb_mutex_synchronize_m(VALUE self)
    {
        if (!rb_block_given_p()) {
            rb_raise(rb_eThreadError, "must be called with a block");
        }

        return rb_mutex_synchronize(self, rb_yield, Qundef);
    }

try_lock → true or false click to toggle source

Attempts to obtain the lock and returns immediately. Returns `true` if the lock was granted.

    VALUE
    rb_mutex_trylock(VALUE self)
    {
        rb_mutex_t *mutex = mutex_ptr(self);

        if (mutex->fiber == 0) {
            rb_fiber_t *fiber = GET_EC()->fiber_ptr;
            rb_thread_t *th = GET_THREAD();
            mutex->fiber = fiber;

            mutex_locked(th, self);
            return Qtrue;
        }

        return Qfalse;
    }

unlock → self click to toggle source

Releases the lock. Raises `ThreadError` if `mutex` wasn’t locked by the current thread.

    VALUE
    rb_mutex_unlock(VALUE self)
    {
        const char *err;
        rb_mutex_t *mutex = mutex_ptr(self);
        rb_thread_t *th = GET_THREAD();

        err = rb_mutex_unlock_th(mutex, th, GET_EC()->fiber_ptr);
        if (err) rb_raise(rb_eThreadError, "%s", err);

        return self;
    }