class 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;
}