use std::sync::{Arc, Condvar, Mutex};
struct MyRwLock<T> {
data: T,
readers_count: usize,
writers_waiting: usize,
mutex: Mutex<()>,
read_cv: Condvar,
write_cv: Condvar,
}
impl<T> MyRwLock<T> {
fn new(data: T) -> Self {
MyRwLock {
data,
readers_count: 0,
writers_waiting: 0,
mutex: Mutex::new(()),
read_cv: Condvar::new(),
write_cv: Condvar::new(),
}
}
fn read(&self) -> ReadGuard<'_, T> {
let mut lock = self.mutex.lock().unwrap();
while self.writers_waiting > 0 {
lock = self.read_cv.wait(lock).unwrap();
}
self.readers_count += 1;
drop(lock);
ReadGuard {
rwlock: self,
}
}
fn write(&self) -> WriteGuard<'_, T> {
let mut lock = self.mutex.lock().unwrap();
self.writers_waiting += 1;
while self.readers_count > 0 || self.writers_waiting > 1 {
lock = self.write_cv.wait(lock).unwrap();
}
self.writers_waiting -= 1;
WriteGuard {
rwlock: self,
}
}
}
struct ReadGuard<'a, T> {
rwlock: &'a MyRwLock<T>,
}
impl<'a, T> Drop for ReadGuard<'a, T> {
fn drop(&mut self) {
let mut lock = self.rwlock.mutex.lock().unwrap();
self.rwlock.readers_count -= 1;
if self.rwlock.readers_count == 0 {
self.rwlock.write_cv.notify_one();
} else {
self.rwlock.read_cv.notify_one();
}
}
}
struct WriteGuard<'a, T> {
rwlock: &'a MyRwLock<T>,
}
impl<'a, T> Drop for WriteGuard<'a, T> {
fn drop(&mut self) {
let mut lock = self.rwlock.mutex.lock().unwrap();
self.rwlock.write_cv.notify_all();
self.rwlock.read_cv.notify_all();
}
}
// 性能分析
### 高读场景
- **性能特性**:由于读操作不互斥,只要没有写操作在进行或等待,多个读操作可以同时进行。减少了锁争用,吞吐量较高。当读操作远远多于写操作时,性能接近无锁状态下的并发读性能。
### 高写场景
- **性能特性**:写操作需要独占锁,并且在等待写操作时,读操作也会被阻塞。随着写操作比例增加,锁争用加剧,吞吐量下降,因为每次写操作都要等待所有读操作完成,并且其他写操作也要排队等待。
### 读写均衡场景
- **性能特性**:性能介于高读和高写场景之间。读操作会因为写操作的等待而偶尔被阻塞,写操作也会因为读操作的进行而等待。合理的同步机制(如使用条件变量通知)在一定程度上缓解锁争用,但整体性能会受到读写操作相互影响的制约。