这是一个超级人为的例子,显示了我想做的事;我有一个HashMap,我想将数据推送到其中,但是我想在一组线程中完成它-真正的例子是我要连接到thread::spawn
内部的远程服务,所以我想尽可能将所有操作都在后台执行,以免阻塞主线程。
我不确定如何重构代码以允许执行我想做的事情-任何建议都会有所帮助!
let mut item_array : HashMap<i32, i32> = HashMap::new();
let mut array: [i32; 3] = [0, 1, 2];
for item in &array {
thread::spawn(|| {
item_array.insert(*item, *item);
});
}
println!("{:?}", item_array);
我收到的错误如下
error[E0597]: `array` does not live long enough
--> src/main.rs:87:17
|
87 | for item in &array {
| ^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `array` is borrowed for `'static`
...
153 | }
| - `array` dropped here while still borrowed
error[E0499]: cannot borrow `item_array` as mutable more than once at a time
--> src/main.rs:88:23
|
88 | thread::spawn(|| {
| - ^^ mutable borrow starts here in previous iteration of loop
| _________|
| |
89 | | item_array.insert(*item, *item);
| | ---------- borrows occur due to use of `item_array` in closure
90 | | });
| |__________- argument requires that `item_array` is borrowed for `'static`
error[E0373]: closure may outlive the current function, but it borrows `item`, which is owned by the current function
--> src/main.rs:88:23
|
88 | thread::spawn(|| {
| ^^ may outlive borrowed value `item`
89 | item_array.insert(*item, *item);
| ---- `item` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src/main.rs:88:9
|
88 | / thread::spawn(|| {
89 | | item_array.insert(*item, *item);
90 | | });
| |__________^
help: to force the closure to take ownership of `item` (and any other referenced variables), use the `move` keyword
|
88 | thread::spawn(move || {
| ^^^^^^^
error[E0373]: closure may outlive the current function, but it borrows `item_array`, which is owned by the current function
--> src/main.rs:88:23
|
88 | thread::spawn(|| {
| ^^ may outlive borrowed value `item_array`
89 | item_array.insert(*item, *item);
| ---------- `item_array` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src/main.rs:88:9
|
88 | / thread::spawn(|| {
89 | | item_array.insert(*item, *item);
90 | | });
| |__________^
help: to force the closure to take ownership of `item_array` (and any other referenced variables), use the `move` keyword
|
88 | thread::spawn(move || {
| ^^^^^^^
error[E0502]: cannot borrow `item_array` as immutable because it is also borrowed as mutable
--> src/main.rs:92:22
|
88 | thread::spawn(|| {
| - -- mutable borrow occurs here
| _________|
| |
89 | | item_array.insert(*item, *item);
| | ---------- first borrow occurs due to use of `item_array` in closure
90 | | });
| |__________- argument requires that `item_array` is borrowed for `'static`
91 | }
92 | println!("{:?}", item_array);
| ^^^^^^^^^^ immutable borrow occurs here
答案 0 :(得分:2)
这里有两个问题(这是多线程Rust的典型问题):
std::thread::spawn
时,它是任何数据 1 )。第一个问题通常通过以下方式解决:
Arc
作为线程安全的共享指针,以确保数据在使用它的所有线程中都寿命更长。并非在所有情况下都可行,但我将按顺序推荐上述解决方案。
第二个问题通常使用诸如Mutex
或RwLock
之类的锁来解决,该锁只允许单个线程一次获取可变的引用。
结合这些,我将解决您的示例,如下所示:
// mutable data is wrapped in a Mutex
let item_array: Mutex<HashMap<i32, i32>> = Mutex::new(HashMap::new());
// immutable data does not have to be wrapped with scoped threads
let array: [i32; 3] = [0, 1, 2];
// using crossbeam::scope from the crossbeam library, which lets
// us reference variables outside the scope (item_array and array)
crossbeam::scope(|s| {
for item in &array {
// copy item (since it is an integer)
let item = *item;
// explicitly reference item_array, since we'll later need to move this
let item_array_ref = &item_array;
// move item and item_array_ref into the closure (instead of referencing,
// which is by default)
s.spawn(move |_| {
// need to call .lock() to aquire a mutable reference to the HashMap
// will wait until the mutable reference is not used by any other threads
let mut item_array_lock = item_array_ref.lock().unwrap();
item_array_lock.insert(item, item);
});
}
// the scope will persist until all threads spawned inside it (with s.spawn) have completed, blocking the current thread,
// ensuring that any referenced data outlives all the threads
})
.unwrap();
// need to call .lock() here as well to get a reference to the HashMap
println!("{:?}", item_array.lock().unwrap());
1 除非数据具有'static
生存期,否则在程序的整个生存期内都可以存在。
答案 1 :(得分:1)