DashMap像这样的代码在 Rust 中使用 a 会产生死锁吗?
// 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
}
此外,在同一线程中迭代仪表板时插入仪表板也会产生死锁。但是,从另一个线程插入仪表板不会产生死锁。真的吗?
这些示例都不会产生死锁。
从文档中:
insert():将键和值插入到映射中。返回与该键关联的旧值(如果有)。
锁定行为:如果在将任何类型的引用保存到地图中时调用,可能会死锁。
iter():在 DashMap 上创建一个迭代器,产生不可变的引用。
锁定行为:如果在将可变引用保存到映射中时调用,可能会死锁。
get_mut():获取对映射中条目的可变引用
锁定行为:如果在保存映射中的任何类型的引用时调用,可能会死锁。
解释:
在前两个示例中,iter()使用了 only ,因此只要不使用将可变引用引入映射的其他操作,就不会出现死锁。
在您的第三个示例中,DashMapb仅再次使用过iter(),因此不会出现死锁。对于 DashMapa有两种可能的执行流程:
a.iter()首先到达,那么线程 2 将必须等待a.get_mut(key),但是一旦线程 1 完成迭代,a线程 2 将能够继续,因此不会出现死锁。a.get_mut(key)首先到达,那么线程 1 将不得不等待,a.iter()但一旦线程 2 完成,它将能够继续,并且不会出现死锁。附加问题:
在同一线程中迭代 DashMap 时插入 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()不会等待整个循环完成,而是两个循环的执行将交错,但它们永远不会在精确的位置执行同时。
| 归档时间: | 
 | 
| 查看次数: | 2475 次 | 
| 最近记录: |