multithreading - 在多个线程中改变共享可变变量

标签 multithreading rust

我想在多个线程中更改一个可变变量。我知道这不是线程安全的,但我想知道 Rust 编译器将如何处理它。所以我使用范围的 map 函数来生成子线程:

use std::thread;

fn break_law(value: &mut i32) {
    *value += 20;
}

fn main() {
    let mut x = 10;

    let handles = (0..10).map(|| {
        thread::spawn(move || {
        break_law(&mut x);
        println!("{:?}", x);
        })
    }).collect();

    for h in handles {
        h.join().unwrap();
    }
}

但是我得到一个错误:

break_law1.rs:10:24: 15:4 error: type mismatch: the type `[closure@break_law1.rs
:10:28: 15:3 x:_]` implements the trait `core::ops::FnMut<()>`, but the trait `c
ore::ops::FnMut<(_,)>` is required (expected tuple, found ()) [E0281]
break_law1.rs:10        let handles = (0..10).map(|| {
break_law1.rs:11                thread::spawn(move || {
break_law1.rs:12                        break_law(&mut x);
break_law1.rs:13                        println!("{:?}", x);
break_law1.rs:14                })
break_law1.rs:15        }).collect();
break_law1.rs:10:24: 15:4 help: run `rustc --explain E0281` to see a detailed ex
planation
break_law1.rs:10:24: 15:4 error: type mismatch: the type `[closure@break_law1.rs
:10:28: 15:3 x:_]` implements the trait `core::ops::FnOnce<()>`, but the trait `
core::ops::FnOnce<(_,)>` is required (expected tuple, found ()) [E0281]
break_law1.rs:10        let handles = (0..10).map(|| {
break_law1.rs:11                thread::spawn(move || {
break_law1.rs:12                        break_law(&mut x);
break_law1.rs:13                        println!("{:?}", x);
break_law1.rs:14                })
break_law1.rs:15        }).collect();
break_law1.rs:10:24: 15:4 help: run `rustc --explain E0281` to see a detailed ex
planation
break_law1.rs:15:5: 15:14 error: type mismatch: the type `[closure@break_law1.rs
:10:28: 15:3 x:_]` implements the trait `core::ops::FnMut<()>`, but the trait `c
ore::ops::FnMut<(_,)>` is required (expected tuple, found ()) [E0281]
break_law1.rs:15        }).collect();
                           ^~~~~~~~~
break_law1.rs:15:5: 15:14 help: run `rustc --explain E0281` to see a detailed ex
planation
break_law1.rs:18:6: 18:14 error: the type of this value must be known in this co
ntext
break_law1.rs:18            h.join().unwrap();
                            ^~~~~~~~
break_law1.rs:17:2: 19:3 note: in this expansion of for loop expansion
error: aborting due to 4 previous errors

根据上面的信息,我得到那个范围的map函数定义是这样的:

// Creates a new iterator that will apply the specified function to each
// element returned by the first, yielding the mapped element instead.
fn map<B, F>(self, f: F) -> Map<Self, F> 
    where F: FnMut(Self::Item) -> B

这看起来很奇怪,但我该如何纠正呢?为什么?

最佳答案

map 的类型签名是说它采用类型参数 ( F ),它是一个闭包 ( FnMut ),传递一个参数,这是迭代器产生的类型 ( (Self::Item) ) 并返回一个 B (-> B)。你缺少的部分是论点:它需要是 .map(|x| { ... })而不是 .map(|| { ... }) .

如果你不关心参数的值,你可以写.map(|_| { ... }) , 使用 _忽略它的模式,或 .map(|_i| { ... }) ,其中领先的_是一个约定,表示一个变量是未使用的(它使编译器对未使用变量的正常警告静音)。

FWIW,错误消息有点长,但它确实包含以下信息:

type mismatch: the type `[closure@break_law1.rs:10:28: 15:3 x:_]` implement
    the trait `core::ops::FnMut<()>`, 
but the trait `core::ops::FnMut<(_,)>` is required

我用换行符来强调区别:编译器提示你传递给 map 的闭包不带参数( FnMut<()> ),当它实际上想要带一个参数时( FnMut<(_,)>_ 表示类型参数还没有足够的信息来完全推断)。

关于multithreading - 在多个线程中改变共享可变变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33499889/

相关文章:

openssl - 错误 : native library `openssl` is being linked to by more than one version of the same package

java - 如何管理CPU资源

c++ - 优雅断言函数不是从多个线程调用的

rust - 如何在 Rust 中实现类似于 @override 的行为

rust - 克隆并返回 Rc 时为 "Expected reference, found struct Rc"

collections - 我如何通过其中一个字段索引一组记录?

rust - 如何改变移动传递的参数?

winforms - 带有 FileSystemWatcher 的 Windows 窗体未启动子窗体

multithreading - Perl Fork 线程捕获输出

java - StreamCorruptedException : invalid type code: AC