问题描述
在此代码示例中,来自 Github page of r2d2:
fn main() {
let manager = r2d2_foodb::FooConnectionManager::new("localhost:1234");
let pool = r2d2::Pool::builder()
.max_size(15)
.build(manager)
.unwrap();
for _ in 0..20 {
let pool = pool.clone();
thread::spawn(move || {
let conn = pool.get().unwrap();
})
}
}
为什么要在循环中克隆 Pool
结构?
解决方法
这是因为循环内产生的线程需要获得 pool
的所有权,因为每个线程的运行时间可能超过 main
。如果 pool
在线程仍在运行时退出,则从线程内部引用 main
拥有的 main
可能会导致引用已被销毁的值。
获得 pool
的所有权要求您在每次循环执行时克隆它,因此每个线程都有自己的副本。
在内部,Pool
是一个 std::sync::Arc
,而 Clone
实现只是简单地克隆了 Arc
。也就是说,Pool
的每个克隆只是一个递增的引用计数。随着线程的创建,引用计数会增加。当线程完成时,它们通过删除 Pool
来减少引用计数,当引用计数达到零时破坏底层连接。