V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
BBCCBB
V2EX  ›  Rust

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

  •  
  •   BBCCBB · 2022-05-18 15:47:24 +08:00 · 1592 次点击
    这是一个创建于 680 天前的主题,其中的信息可能已经有所发展或是发生改变。
    
    
    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 社区 /论坛 /讨论区

    13 条回复    2022-05-19 11:04:06 +08:00
    reter
        1
    reter  
       2022-05-18 16:15:47 +08:00   ❤️ 1
    我分析,编译器认为只有 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
        2
    BBCCBB  
    OP
       2022-05-18 16:20:22 +08:00
    @reter 有道理, 我再回去好好看看多线程这里. 多谢, 这些小坑烧脑壳
    liuhan907
        3
    liuhan907  
       2022-05-18 17:14:07 +08:00
    @BBCCBB
    你的 p 的具体类型 Point<i32> 字段全满足 Sync ,所以 Point<i32> 也自动满足 Sync ,因此跨线程共享是安全的。你可以尝试用 Point<String> 试试看。
    BBCCBB
        4
    BBCCBB  
    OP
       2022-05-18 18:04:13 +08:00
    @liuhan907 对的, 我也试过这个..

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


    论坛的话,https://rustcc.cn/ 也不错,rustdesk 也在这个论坛上活跃
    BBCCBB
        13
    BBCCBB  
    OP
       2022-05-19 11:04:06 +08:00
    @reter 感谢, 10 楼链接里就是原理了... 新特性,哈哈, 不是 Copy, 是 disjoint capture
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1373 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 17:41 · PVG 01:41 · LAX 10:41 · JFK 13:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.