rust 中的并发螺纹:“join on handle”执行什么操作?

lnlaulya  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(223)

Rust documentation的以下代码中,它讨论了Rust中的并发线程。

use std::sync::{Arc, Mutex};
    use std::thread;

    fn main() {
        let counter = Arc::new(Mutex::new(0));
        let mut handles = vec![];

        for _ in 0..10 {
            let counter = Arc::clone(&counter);
            let handle = thread::spawn(move || {
                let mut num = counter.lock().unwrap();

                *num += 1;
            });
            handles.push(handle);
        }

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

        println!("Result: {}", *counter.lock().unwrap());
    }

我仍然无法理解句柄的for循环的概念
也就是

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

文档中说 “我们在每个句柄上调用join以确保所有线程都完成。“ 在一个实验中,我注解掉了循环的句柄,得到的输出是8而不是10。当我将循环改为1000时,当句柄循环被注解时,我得到的输出是999。这是怎么回事?8和999是如何变成输出的?

**编辑:**我发现this documentation涉及到处理和线程的一般概念。

[1]: https://doc.rust-lang.org/book/ch16-03-shared-state.html
jpfvwuh4

jpfvwuh41#

我仍然无法理解句柄的for循环的概念
JoinHandle::join阻塞,直到相应的线程执行完毕(因此函数已经到达它的末尾),这是它的大部分内容(有用的是,它还生成线程的函数返回的任何内容)。
当我把循环改为1000时,当句柄循环被注解时,我得到了999。这里发生了什么?8 & 999怎么会变成输出呢?
如果不对线程执行join,则线程与主线程之间会发生竞争(main函数)。
1.创建所有线程
1.将每个线程添加到向量
1.锁定柜台
这将根据系统负载和操作系统调度细节而改变,尽管主线程的大部分延迟将是......产生更多的线程(与产生一个线程相比,获取一个锁和增加一个数字是便宜的),这就是为什么大多数线程在打印结果时已经完成。如果您增加每个线程的工作量,或者改变线程产生的方式,您将看到不同的竞争。

yhuiod9q

yhuiod9q2#

join()所做的只是等待线程完成,它要求操作系统阻塞主线程(调用join()的线程),直到被加入的线程完成,并收集其状态。
在调用join()之前,你只知道你已经把线程交给了操作系统。你不知道在代码的后面,它是否已经开始,正在运行,已经完成,被操作系统杀死,或者已经崩溃(),等等。
在调用join()之前,您对共享counter的唯一了解是,您可以在一致的状态下读取它(多亏了互斥体),也就是说,不会冒主线程和另一个线程之间可能正在递增它的竞争条件的风险。

相关问题