类 Thread::Mutex
Thread::Mutex
实现了一个简单的信号量,可用于协调多个并发线程对共享数据的访问。
示例
semaphore = Thread::Mutex.new a = Thread.new { semaphore.synchronize { # access shared resource } } b = Thread.new { semaphore.synchronize { # access shared resource } }
公共类方法
Thread::Mutex.new → mutex 点击切换源代码
创建一个新的 Mutex
static VALUE mutex_initialize(VALUE self) { return self; }
公共实例方法
lock → self 点击切换源代码
尝试获取锁,如果锁不可用则等待。如果当前线程已锁定 mutex
,则会引发 ThreadError
。
VALUE rb_mutex_lock(VALUE self) { return do_mutex_lock(self, 1); }
locked? → true 或 false 点击切换源代码
如果此锁当前被某个线程持有,则返回 true
。
VALUE rb_mutex_locked_p(VALUE self) { rb_mutex_t *mutex = mutex_ptr(self); return RBOOL(mutex->fiber); }
owned? → true 或 false 点击切换源代码
如果此锁当前被当前线程持有,则返回 true
。
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 或 nil 点击切换源代码
释放锁并休眠 timeout
秒(如果给出且非空)或永远休眠。如果当前线程未锁定 mutex
,则会引发 ThreadError
。
当线程下次被唤醒时,它将尝试重新获取锁。
请注意,此方法可以在没有显式 Thread#wakeup
调用时唤醒。例如,接收信号等。
如果被唤醒,则返回以秒为单位的休眠时间,如果超时,则返回 nil
。
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 { ... } → 块的结果 点击切换源代码
获取锁,运行块,并在块完成时释放锁。请参阅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 或 false 点击切换源代码
尝试获取锁并立即返回。如果锁被授予,则返回true
。
VALUE rb_mutex_trylock(VALUE self) { rb_mutex_t *mutex = mutex_ptr(self); if (mutex->fiber == 0) { RUBY_DEBUG_LOG("%p ok", mutex); rb_fiber_t *fiber = GET_EC()->fiber_ptr; rb_thread_t *th = GET_THREAD(); mutex->fiber = fiber; mutex_locked(th, self); return Qtrue; } else { RUBY_DEBUG_LOG("%p ng", mutex); return Qfalse; } }
unlock → self 点击切换源代码
释放锁。如果mutex
没有被当前线程锁定,则会引发ThreadError
。
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; }