使用 Rust Dashmap 这些代码会产生死锁吗?
Will these code produce a deadlock using Rust Dashmap?
在 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 不会产生死锁。是真的吗?
None 个示例会产生死锁。
来自文档:
insert()
:向映射中插入一个键和一个值。 Returns 与密钥关联的旧值(如果有的话)。
锁定行为:如果在映射中持有任何类型的引用时调用可能会死锁。
iter()
:在 DashMap 上创建一个迭代器,产生不可变引用。
锁定行为:如果在映射中持有可变引用时调用,可能会死锁。
get_mut()
: 获取映射中条目的可变引用
锁定行为:如果在映射中持有任何类型的引用时调用可能会死锁。
解释:
在您的前两个示例中,仅使用了 iter()
,因此只要不使用其他将可变引用引入映射的操作,就不会出现死锁。
在您的第三个示例中,DashMap b
仅再次与 iter()
一起使用,因此那里没有死锁。对于 DashMap a
有两种可能的执行流程:
- 如果线程 1 首先到达
a.iter()
,则线程 2 将不得不在 a.get_mut(key)
处等待,但是一旦线程 1 完成对 a
的迭代,线程 2 将能够继续,所以不会有死锁。
- 如果线程 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 而在另一个线程迭代 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()
可能不会等待整个循环完成才开始,而是执行两个循环中的一个将交错,但它们永远不会同时执行。
在 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 不会产生死锁。是真的吗?
None 个示例会产生死锁。
来自文档:
insert()
:向映射中插入一个键和一个值。 Returns 与密钥关联的旧值(如果有的话)。
锁定行为:如果在映射中持有任何类型的引用时调用可能会死锁。
iter()
:在 DashMap 上创建一个迭代器,产生不可变引用。
锁定行为:如果在映射中持有可变引用时调用,可能会死锁。
get_mut()
: 获取映射中条目的可变引用
锁定行为:如果在映射中持有任何类型的引用时调用可能会死锁。
解释:
在您的前两个示例中,仅使用了 iter()
,因此只要不使用其他将可变引用引入映射的操作,就不会出现死锁。
在您的第三个示例中,DashMap b
仅再次与 iter()
一起使用,因此那里没有死锁。对于 DashMap a
有两种可能的执行流程:
- 如果线程 1 首先到达
a.iter()
,则线程 2 将不得不在a.get_mut(key)
处等待,但是一旦线程 1 完成对a
的迭代,线程 2 将能够继续,所以不会有死锁。 - 如果线程 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 而在另一个线程迭代 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()
可能不会等待整个循环完成才开始,而是执行两个循环中的一个将交错,但它们永远不会同时执行。