如果需要加锁,应该加在DbSingle的成员上
问题分析
当前设计的问题:
锁粒度太大:整个 DbSingle 实例被锁,影响并发性能
职责混淆:DbSingle 本身可能有内部状态,但不需要整个对象都被保护
使用不便:调用者每次都要 .lock().unwrap(),使用体验差
改进方案
方案1:内部成员加锁(推荐)
rust
pub struct DbSingle {
inner: Arc<Mutex<DbSingleInner>>, // 或 RwLock
// 其他只读字段
}
struct DbSingleInner {
// 需要同步的可变状态
connections: Vec<Connection>,
cache: HashMap<String, Data>,
}
impl DbSingle {
pub fn new() -> Self {
Self {
inner: Arc::new(Mutex::new(DbSingleInner {
connections: Vec::new(),
cache: HashMap::new(),
})),
}
}
pub fn find_bean(&self) -> Option<Arc<Mutex<DbSingle>>> {
// 内部处理锁
let mut inner = self.inner.lock().unwrap();
// 具体逻辑…
Some(Arc::new(Mutex::new(self.clone())))
}
}
方案2:使用 RwLock 提高读性能
rust
pub struct DbSingle {
inner: Arc<RwLock<DbSingleInner>>,
}
impl DbSingle {
pub fn find_bean(&self) -> Option<…> {
let read_guard = self.inner.read().unwrap();
// 读操作
drop(read_guard); // 及时释放
let mut write_guard = self.inner.write().unwrap();
// 写操作
}
}
方案3:无锁设计(最优)
如果可能,使用原子操作或不可变数据结构:
rust
pub struct DbSingle {
state: Arc<AtomicState>, // 使用原子类型
// 或使用 DashMap 等并发容器
cache: DashMap<String, Data>,
}
方案4:调整 DI 注册方式
rust
// 在 DI 容器中
pub fn find_bean_db_single() -> Option<Arc<DbSingle>> {
DbSingle::find_bean() // 返回 Arc<DbSingle>
}
// DbSingle 内部处理并发
impl DbSingle {
pub fn find_bean() -> Option<Arc<Self>> {
// 使用内部的并发控制
Some(Arc::new(Self {
// 初始化
}))
}
}
最终建议
根据你的使用场景选择:
如果 DbSingle 主要是读操作:使用 RwLock<DbSingleInner>
如果需要高并发写:使用 DashMap 等并发容器
如果状态简单:使用原子类型(AtomicUsize、AtomicBool 等)
如果可能:重新设计为无状态服务,完全避免锁
rust
// 推荐实现
pub struct DbSingle {
connections: Arc<Mutex<Vec<Connection>>>, // 只锁连接池
cache: Arc<DashMap<String, Data>>, // 无锁并发Map
config: DbConfig, // 只读配置
}
pub fn find_bean_db_single() -> Option<Arc<DbSingle>> {
DbSingle::find_bean()
}
这样既保证了线程安全,又最小化了锁竞争,提高了并发性能。



