讀寫鎖顧名思義就是隻容許單進程同時寫,在數據沒有被寫的狀況下容許多進程同時讀,的鎖。測試
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); }