这样的代码会不会在Rust中使用DashMap
产生死锁?
// snippet_1
let a = DashMap::new();
let b = DashMap::new();
// thread1
for v in a.iter(){
xxx
}
for v in b.iter(){
xxx
}
//thread2
for v in b.iter(){
xxx
}
for v in a.iter(){
xxx
}
// snippet_2
let a = DashMap::new();
let b = DashMap::new();
// thread1
for v in a.iter(){
xxx
}
for v in b.iter(){
xxx
}
//thread2
for v in b.iter(){
xxx
for v in a.iter() {
xxx
}
xxx
}
// snippet_3
let a = DashMap::new();
let b = DashMap::new();
// thread1
for v in a.iter(){
xxx
}
for v in b.iter(){
xxx
}
//thread2
for v in b.iter(){
xxx
let Some(v) = a.get_mut(key){
xxx
}
xxx
}
此外,在同一个线程中迭代时,插入到dashmap中将产生死锁。但是,从另一个线程插入到dashmap不会产生死锁。这是真的吗?
发布于 2021-12-10 09:35:22
所有这些示例都不会产生死锁。
来自文档的:
insert()
:在映射中插入一个键和一个值。返回与键关联的旧值(如果存在的话)。
锁定行为:如果将任何类型的引用保存到映射中时调用,则可能出现死锁。
iter()
:在生成不可变引用的DashMap上创建一个迭代器。
锁定行为:如果将可变引用保存到映射中时调用,则可能出现死锁。
get_mut()
:获取映射中一个条目的可变引用
锁定行为:如果将任何类型的引用保存到映射中时调用,则可能出现死锁。
Explanation:
在前两个示例中,只使用iter()
,因此只要不使用将可变引用包含到映射中的其他操作,就不会出现死锁。
在您的第三个示例中,DashMap b
只与iter()
一起使用,因此没有死锁。对于DashMap a
,有两个可能的执行流:
a.iter()
,那么线程2必须在a.get_mut(key)
等待,但是一旦线程1完成了对a
线程2的迭代,那么就不会出现死锁。如果线程2首先到达a.get_mut(key)
,那么线程1必须在a.iter()
等待,但是一旦线程2完成,它将能够继续,并且不会出现死锁。H 226G 227
附加问题
在同一个线程中迭代DashMap时,插入到它中将产生死锁。
示例
for v in a.iter() { // This takes a reference into `a`
a.insert(...) // Will deadlock because you hold a reference into `a`
}
从一个线程插入到DashMap中,而在另一个线程中迭代它,不会产生死锁,其中一个只会等待另一个线程。
示例
//thread1
for v in a.iter(){ //If thread2 reaches `insert()` first, this will wait until it has finished.
xxx
}
//thread2
for i in 1..1000 {
a.insert(i, i); // If thread1 reaches `iter()` first, this will wait until it has finished.
}
需要注意的是,在最后一个例子和问题的第三个例子中,insert()和iter()可能不会等待整个循环在开始之前完成,相反,两个循环的执行将被交错,但它们永远不会在完全同时执行。
https://stackoverflow.com/questions/70299926
复制相似问题