首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在多个线程中变异共享可变变量

在多个线程中变异共享可变变量
EN

Stack Overflow用户
提问于 2015-11-03 13:04:36
回答 2查看 720关注 0票数 0

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

代码语言:javascript
复制
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();
    }
}

但我发现了一个错误:

代码语言:javascript
复制
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函数定义如下:

代码语言:javascript
复制
// 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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-03 13:25:18

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

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

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

代码语言:javascript
复制
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<(_,)>_表示一个类型参数,它还没有得到足够的信息来充分推断)。

票数 0
EN

Stack Overflow用户

发布于 2015-11-03 13:52:41

顺便说一句,即使像上面所示的修复了参数编号问题之后,您也不会得到您想要的行为。代码将成功编译,因为每个线程都将收到变量的变量x,只要Rust中的整型实现Copy特性。

我认为正确的示例应该如下所示:

代码语言:javascript
复制
fn break_law(value: &mut i32) {
    *value += 20;
}

fn main() {
    let mut x = 10;
    let ref_x = &mut x;

    let handles: Vec<_> = (0..10).map(|_| {
        thread::spawn(move || {
            break_law(ref_x);
            println!("{:?}", x);
        })
    }).collect();

    for h in handles {
        h.join().unwrap();
    }
} 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33499889

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档