为什么要把Connection pool克隆到这里?
Why is the Connection pool cloned here?
在此代码示例中,来自 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
。从线程内部引用 main
拥有的 pool
可能会导致引用一个已经被销毁的值,如果 main
在线程仍在 运行ning 时退出。
获取 pool
的所有权需要您在每次循环执行时克隆它,因此每个线程都有自己的副本。
在内部,Pool
是一个 std::sync::Arc
,Clone
实现只是克隆了 Arc
。也就是说,Pool
的每个克隆只是一个递增的引用计数。随着线程的创建,引用计数会增加。当线程完成时,它们通过删除 Pool
来减少引用计数,当引用计数达到零时破坏底层连接。
在此代码示例中,来自 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
。从线程内部引用 main
拥有的 pool
可能会导致引用一个已经被销毁的值,如果 main
在线程仍在 运行ning 时退出。
获取 pool
的所有权需要您在每次循环执行时克隆它,因此每个线程都有自己的副本。
在内部,Pool
是一个 std::sync::Arc
,Clone
实现只是克隆了 Arc
。也就是说,Pool
的每个克隆只是一个递增的引用计数。随着线程的创建,引用计数会增加。当线程完成时,它们通过删除 Pool
来减少引用计数,当引用计数达到零时破坏底层连接。