读写锁顾名思义就是只容许单进程同时写,在数据没有被写的状况下容许多进程同时读,的锁。测试
rust 里和 Mutex 相似,使用RAII(Resource Acquisition Is Initialization)来保证在值被Drop的时候自动解锁。而 go 里依然是须要手动解锁。ui
import ( . "sync" "sync/atomic" ) const NumIterations = 1000 const NumReaders = 1000 func writer(rwm *RWMutex, activity *int32, cdone chan bool) { for i := 0; i < NumIterations; i++ { rwm.Lock() n := atomic.AddInt32(activity, 10000) if n != 10000 { panic(fmt.Sprintf("wlock(%d)\n", n)) } atomic.AddInt32(activity, -10000) rwm.Unlock() } cdone <- true } func reader(rwm *RWMutex, activity *int32, cdone chan bool) { for i := 0; i < NumIterations; i++ { rwm.RLock() n := atomic.AddInt32(activity, 1) // 即便只得到了读锁,依旧能够修改数据 // 只是禁止别的进程获取写锁 if n < 1 || n > 10000 { panic(fmt.Sprintf("wlock(%d)\n", n)) } atomic.AddInt32(activity, -1) rwm.RUnlock() } cdone <- true } func main() { var activity int32 var rwm sync.RWMutex cdone := make(chan bool) go writer(&rwm, &activity, cdone) var i int for i = 0; i < NumReaders/2; i++ { go reader(&rwm, &activity, cdone) } go writer(&rwm, &activity, cdone) for ; i < NumReaders; i++ { go reader(&rwm, &activity, cdone) } for i := 0; i < 2+NumReaders; i++ { <-cdone } }
use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, RwLock}; use std::thread; const NumIterations: usize = 1000; // 因为直接使用操做系统的 Thread,因此不能开太多 const NumReaders: usize = 500; fn main() { let data = Arc::new(RwLock::new(0)); let (tx, rx) = channel(); { let (data, tx) = (data.clone(), tx.clone()); thread::spawn(move || { writer(data, tx); }); } for _ in 0..NumReaders/2 { let (data, tx) = (data.clone(), tx.clone()); thread::spawn(move || { reader(data, tx); }); } { let (data, tx) = (data.clone(), tx.clone()); thread::spawn(move || { writer(data, tx); }); } for _ in NumReaders/2..NumReaders { let (data, tx) = (data.clone(), tx.clone()); thread::spawn(move || { reader(data, tx); }); } for _ in 0..NumReaders { rx.recv(); } } fn writer(data: Arc<RwLock<i32>>, tx: Sender<bool>) { for _ in 0..NumIterations { let mut w = data.write().unwrap(); *w += 10000; assert!(*w == 10000); *w -= 10000; } tx.send(true); } fn reader(data: Arc<RwLock<i32>>, tx: Sender<bool>) { for _ in 0..NumIterations { // 只得到读锁是没法写数据的 let r = data.read().unwrap(); assert!(*r == 0); } tx.send(true); }