[Rust] 为啥我这里的 p 可以在多个线程间转移所有权并使用呢?

2022-05-18 15:47:24 +08:00
 BBCCBB


use std::thread;

fn main() {
    struct Point<T> {
        pub x: T,
    }

    let mut p = Point { x: 32 };
    

    let mut vals = Vec::new();
    for _ in 0..2 {
        let h = thread::spawn(move || {
            p.x = 5;
            println!("{}", p.x);
        });
        vals.push(h);
    }

    for v in vals {
        v.join().unwrap();
    }
    println!("{}", p.x);  // 32
}

输出结果是两个 5 和最后的 32, 也就是说线程里修改对主线程无效

playground url: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=bf8936b4cc64c1f3124e926e81d9b4d6

DDDD -_-

我这里的变量 p 为啥能在多个线程间修改和使用呢? 懂的兄弟带带我, 谢谢.

同时求一个好的 rust 社区 /论坛 /讨论区

1631 次点击
所在节点    Rust
13 条回复
reter
2022-05-18 16:15:47 +08:00
我分析,编译器认为只有 p.x 被移动,然后 p.x 默认是 i32 类型, 自动实现了 Copy, 所以在 move 闭包下,创建了新的变量, 复制了 p.x 的值。

如果 p 里面有其它不可移动的字段,然后在 move 闭包里面 进行了操作,那么无法通过编译。


https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a93e02138c3df6841f402b0ccbb7d7be
BBCCBB
2022-05-18 16:20:22 +08:00
@reter 有道理, 我再回去好好看看多线程这里. 多谢, 这些小坑烧脑壳
liuhan907
2022-05-18 17:14:07 +08:00
@BBCCBB
你的 p 的具体类型 Point<i32> 字段全满足 Sync ,所以 Point<i32> 也自动满足 Sync ,因此跨线程共享是安全的。你可以尝试用 Point<String> 试试看。
BBCCBB
2022-05-18 18:04:13 +08:00
@liuhan907 对的, 我也试过这个..

```rust
fn isSync<T: Sync>(_: &T) {}
isSync(&p);
```
我再去仔细看下 Sync/Send, 多谢.
BBCCBB
2022-05-18 18:05:01 +08:00
@liuhan907 还有就是我明确使用 move. 但 p 所有权并没有转进去.==
liuhan907
2022-05-18 18:46:38 +08:00
@BBCCBB
和别人交流了一下,这个就是部分捕获。实际上被 move 的是单独的那个 x , @reter 老哥就是对的。
BBCCBB
2022-05-18 20:47:36 +08:00
@liuhan907 大佬有这方面的文档吗? 以后出了问题我好去翻翻,, 还有就是有啥 rust 论坛吗, dddd
mr0joker
2022-05-18 23:31:15 +08:00
rust 官网不就有个交流的地方
https://users.rust-lang.org/
mr0joker
2022-05-18 23:32:36 +08:00
接 8 楼,个人认为那个网站是“好的”
Buges
2022-05-19 01:41:59 +08:00
这是 rust 2021 edition 的新特性 https://doc.rust-lang.org/edition-guide/rust-2021/disjoint-capture-in-closures.html
move 的只有 x ,而 x 实现了 Copy 。
BBCCBB
2022-05-19 08:57:29 +08:00
@mr0joker 多谢多谢.
@Buges 牛逼, 有理有据,令人信服
reter
2022-05-19 10:54:12 +08:00
我只知道 struct 可以只 move 部分字段,在闭包里还没见过部分捕获。


论坛的话,https://rustcc.cn/ 也不错,rustdesk 也在这个论坛上活跃
BBCCBB
2022-05-19 11:04:06 +08:00
@reter 感谢, 10 楼链接里就是原理了... 新特性,哈哈, 不是 Copy, 是 disjoint capture

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/853726

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX