1 个不稳定版本
使用旧版 Rust 2015
0.1.0 | 2017年3月1日 |
---|
#1184 在 并发 中
20KB
356 行
libmcs
这个Rust库提供了使用MCS锁算法的互斥锁API。
示例
以下示例来自std::sync::Mutex
的文档。
它表明mcs::Mutex
可以与std::sync::Mutex
互换使用。
extern crate libmcs;
use std::sync::Arc;
use std::thread;
use std::sync::mpsc::channel;
use libmcs::Mutex;
const N: usize = 10;
// Spawn a few threads to increment a shared variable (non-atomically), and
// let the main thread know once all increments are done.
//
// Here we're using an Arc to share memory among threads, and the data inside
// the Arc is protected with a mutex.
let data = Arc::new(Mutex::new(0));
let (tx, rx) = channel();
for _ in 0..10 {
let (data, tx) = (data.clone(), tx.clone());
thread::spawn(move || {
// The shared state can only be accessed once the lock is held.
// Our non-atomic increment is safe because we're the only thread
// which can access the shared state when the lock is held.
//
// We unwrap() the return value to assert that we are not expecting
// threads to ever fail while holding the lock.
let mut data = data.lock().unwrap();
*data += 1;
if *data == N {
tx.send(()).unwrap();
}
// the lock is unlocked here when `data` goes out of scope.
});
}
rx.recv().unwrap();
// Recovering from a poisoned mutex
extern crate libmcs;
use std::sync::Arc;
use std::thread;
use libmcs::Mutex;
let lock = Arc::new(Mutex::new(0_u32));
let lock2 = lock.clone();
let _ = thread::spawn(move || -> () {
// This thread will acquire the mutex first, unwrapping the result of
// `lock` because the lock has not been poisoned.
let _guard = lock2.lock().unwrap();
// This panic while holding the lock (`_guard` is in scope) will poison
// the mutex.
panic!();
}).join();
// The lock is poisoned by this point, but the returned result can be
// pattern matched on to return the underlying guard on both branches.
let mut guard = match lock.lock() {
Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(),
};
*guard += 1;
关于MCS锁
MCS锁这样的基于队列的自旋锁被认为比简单的自旋锁具有更好的可伸缩性,因为其分布式特性。然而,MCS锁的缺点是它传统上需要传递一个显式的参数,其类型是队列节点的指针。在Rust语法中,典型的MCS锁API将如下所示
fn lock(q: *mut qnode);
fn unlock(q: *mut qnode);
然而,此crate的API没有这样的限制,因为LockGuard
隐式处理了队列节点。因此,它可以替代std::sync::Mutex
使用。