Mutex 中的可变借用失败
Mutable borrow fail in Mutex
我收到有关 Mutex 中可变借用失败的错误。
这是代码。
现在好了。但是,如果取消注释这两行,它将无法编译,这会将 state
包装到互斥锁中并将其展开。
为什么 Mutex 会有所不同?
use std::collections::HashMap;
use std::sync::Mutex;
struct State {
h1: HashMap<String, String>,
h2: HashMap<String, String>,
}
fn main() {
let mut state = State {
h1: HashMap::new(),
h2: HashMap::new(),
};
// It fails to compile if uncommenting these 2 lines!
//let state = Mutex::new(state);
//let mut state = state.lock().unwrap();
let v1 = state.h1.get_mut("abc").unwrap();
let v2 = state.h2.get_mut("abc").unwrap();
v1.push_str("123");
v2.push_str("123");
}
如果取消注释 2 行的错误:
error[E0499]: cannot borrow `state` as mutable more than once at a time
--> tmp.rs:20:14
|
19 | let v1 = state.h1.get_mut("abc").unwrap();
| ----- first mutable borrow occurs here
20 | let v2 = state.h2.get_mut("abc").unwrap();
| ^^^^^ second mutable borrow occurs here
21 | v1.push_str("123");
| -- first borrow later used here
===编辑===
如果更改一些代码顺序就可以了:
let state = Mutex::new(state);
let mut state = state.lock().unwrap();
let v1 = state.h1.get_mut("abc").unwrap();
v1.push_str("123");
let v2 = state.h2.get_mut("abc").unwrap();
v2.push_str("123");
似乎 v1
持有 state
的引用。如果v1
结束,则丢弃引用,然后state
可以再次借用。
为什么 v1
持有 state
的引用?
====编辑====
@Alexey Larionov 给出了答案。我发现了一个类似的question。我应该通过 deref_mut()
手动从 MutexGuard 中获取 state
。所以添加这一行就可以了:
let state = state.deref_mut();
通过这样做,您可以获取 2 个对状态本身的可变引用。要解决它,您可以重新调整 get_mut 调用之一:
fn main() {
let mut state = State {
h1: HashMap::new(),
h2: HashMap::new(),
};
// It fails to compile if uncommenting these 2 lines!
let state = Mutex::new(state);
let mut state = state.lock().unwrap();
{
let v1 = state.h1.get_mut("abc").unwrap();
v1.push_str("123");
}
let v2 = state.h2.get_mut("abc").unwrap();
v2.push_str("123");
}
这样,当您获得第二个参考时,第一个参考已经被丢弃。
只是为了详细说明@Netwave 的回答,以防万一没有 Mutex
你不会得到这样的错误,因为这样做
let mut state = State {
h1: HashMap::new(),
h2: HashMap::new(),
};
let v1 = state.h1.get_mut("abc").unwrap();
let v2 = state.h2.get_mut("abc").unwrap();
v1
可变借用state.h1
,v2
可变借用state.h2
,两者都算作state
的不可变借用,以防止将 state
移出(例如 let state2 = state;
而存在其他借用)。由于所有借用规则都已满足(或者 每个对象最多有一个可变借用 或 每个对象最多有多个不可变借用),允许借用。
在Mutex
的情况下这一行
let mut state = state.lock().unwrap();
生成类型 MutexGuard::<State>
的 state
。通过这种方式使用它
let v1 = state.h1.get_mut("abc").unwrap();
Rust 不会在 MutexGuard::<State>
中找到 h1
,这就是为什么它将使用 DerefMut
特征从中隐式地获取 &mut State
。那就是你可变地借用 state
的地方。由于您稍后对 v2
使用了类似的构造,因此您将尝试在 state
上获得第二个可变借用,从而收到错误
我收到有关 Mutex 中可变借用失败的错误。
这是代码。
现在好了。但是,如果取消注释这两行,它将无法编译,这会将 state
包装到互斥锁中并将其展开。
为什么 Mutex 会有所不同?
use std::collections::HashMap;
use std::sync::Mutex;
struct State {
h1: HashMap<String, String>,
h2: HashMap<String, String>,
}
fn main() {
let mut state = State {
h1: HashMap::new(),
h2: HashMap::new(),
};
// It fails to compile if uncommenting these 2 lines!
//let state = Mutex::new(state);
//let mut state = state.lock().unwrap();
let v1 = state.h1.get_mut("abc").unwrap();
let v2 = state.h2.get_mut("abc").unwrap();
v1.push_str("123");
v2.push_str("123");
}
如果取消注释 2 行的错误:
error[E0499]: cannot borrow `state` as mutable more than once at a time
--> tmp.rs:20:14
|
19 | let v1 = state.h1.get_mut("abc").unwrap();
| ----- first mutable borrow occurs here
20 | let v2 = state.h2.get_mut("abc").unwrap();
| ^^^^^ second mutable borrow occurs here
21 | v1.push_str("123");
| -- first borrow later used here
===编辑===
如果更改一些代码顺序就可以了:
let state = Mutex::new(state);
let mut state = state.lock().unwrap();
let v1 = state.h1.get_mut("abc").unwrap();
v1.push_str("123");
let v2 = state.h2.get_mut("abc").unwrap();
v2.push_str("123");
似乎 v1
持有 state
的引用。如果v1
结束,则丢弃引用,然后state
可以再次借用。
为什么 v1
持有 state
的引用?
====编辑====
@Alexey Larionov 给出了答案。我发现了一个类似的question。我应该通过 deref_mut()
手动从 MutexGuard 中获取 state
。所以添加这一行就可以了:
let state = state.deref_mut();
通过这样做,您可以获取 2 个对状态本身的可变引用。要解决它,您可以重新调整 get_mut 调用之一:
fn main() {
let mut state = State {
h1: HashMap::new(),
h2: HashMap::new(),
};
// It fails to compile if uncommenting these 2 lines!
let state = Mutex::new(state);
let mut state = state.lock().unwrap();
{
let v1 = state.h1.get_mut("abc").unwrap();
v1.push_str("123");
}
let v2 = state.h2.get_mut("abc").unwrap();
v2.push_str("123");
}
这样,当您获得第二个参考时,第一个参考已经被丢弃。
只是为了详细说明@Netwave 的回答,以防万一没有 Mutex
你不会得到这样的错误,因为这样做
let mut state = State {
h1: HashMap::new(),
h2: HashMap::new(),
};
let v1 = state.h1.get_mut("abc").unwrap();
let v2 = state.h2.get_mut("abc").unwrap();
v1
可变借用state.h1
,v2
可变借用state.h2
,两者都算作state
的不可变借用,以防止将 state
移出(例如 let state2 = state;
而存在其他借用)。由于所有借用规则都已满足(或者 每个对象最多有一个可变借用 或 每个对象最多有多个不可变借用),允许借用。
在Mutex
的情况下这一行
let mut state = state.lock().unwrap();
生成类型 MutexGuard::<State>
的 state
。通过这种方式使用它
let v1 = state.h1.get_mut("abc").unwrap();
Rust 不会在 MutexGuard::<State>
中找到 h1
,这就是为什么它将使用 DerefMut
特征从中隐式地获取 &mut State
。那就是你可变地借用 state
的地方。由于您稍后对 v2
使用了类似的构造,因此您将尝试在 state
上获得第二个可变借用,从而收到错误