gpt4 book ai didi

multithreading - 如何在线程之间共享对 AtomicBool 的访问?

转载 作者:行者123 更新时间:2023-11-29 07:49:20 25 4
gpt4 key购买 nike

我有这个小程序 - 本质上我希望一个线程能够通过结构中的共享 bool 值告诉另一个线程停止。

use std::thread;
use std::thread::JoinHandle;
use std::time::Duration;
use std::sync::atomic::{AtomicBool, Ordering};

struct Test {
should_stop: AtomicBool,
running_thread_handles: Vec<JoinHandle<()>>
}

impl Test {
fn new() -> Test {
Test {
should_stop: AtomicBool::new(false),
running_thread_handles: Vec::new()
}
}

fn stop(&mut self) {
self.should_stop.store(true, Ordering::Relaxed);
}

fn start(&mut self) {
let handle = thread::spawn(move || {
loop {
println!("Looping");
thread::sleep(Duration::from_millis(500));

// I want to effectively do this...
/*
if self.stop_bool.load(Ordering::Relaxed) {
println!("Stopping");
break;
}*/
}
});

self.running_thread_handles.push(handle);
}
}

impl Drop for Test {
fn drop(&mut self) {
self.stop();

// Here I want to iterate the self.running_thread_handles and
// make sure they are cleaned up
}
}

// I expect to see a 4 "Looping" messages and then a "Stopping" message
fn main() {
let mut test = Test::new();
test.start();
thread::sleep(Duration::from_millis(2000));
test.stop();
}

也许有更好的方法,但我认为这可能是稍微了解生命周期的好方法。

我认为我只需要一个 Arc 所以我尝试了这个:

fn start(&mut self) {
let stop_bool = Arc::new(&self.should_stop).clone();

let handle = thread::spawn(move || {
loop {
println!("Looping");
thread::sleep(Duration::from_millis(500));

if stop_bool.load(Ordering::Relaxed) {
println!("Stopping");
break;
}
}
});

self.running_thread_handles.push(handle);
}

这给了我这个错误:

error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements

我认为编译器不理解线程的生命周期,因为我所做的只是将句柄存储在向量中,所以我需要以某种方式告诉它,但如何呢?

如果我像这样声明结构体,我会更接近于让它发挥作用吗?

struct Test<'a> {
should_stop: AtomicBool,
running_thread_handles: &'a Vec<JoinHandle<()>>
}

我还有一些次要的、相关的麻烦,我终生无法弄清楚如何遍历我的句柄向量并在 Drop impl 中调用它们的任何函数。我想这个问题的解决方案是相关的,所以我不会问这个问题。

最佳答案

线程间访问变量有两种方式:

  • 借用,需要保证变量的生命周期超过线程的生命周期
  • 共享所有权(通过 Arc ):

目前标准库不支持借用,尽管第 3 方 crate 如 crossbeam提供它。对于共享所有权,Arc确实有可能……

...但是您需要考虑您在 Arc 中输入的内容小心:

let stop_bool = Arc::new(&self.should_stop).clone();

在这里,您正在创建一个 Arc<&'a AtomicBool>来自&'a self ,因此您共享对借用引用的所有权。我会让你回到上面的解释:标准库还不支持跨线程借用。

你需要一个Arc<AtomicBool>为了适当的共享所有权,这是通过更改 Test 来完成的:

struct Test {
should_stop: Arc<AtomicBool>,
running_thread_handles: Vec<JoinHandle<()>>
}

然后,克隆它很容易:

let stop_bool = self.should_stop.clone();

关于multithreading - 如何在线程之间共享对 AtomicBool 的访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33911792/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com