Rust中的后台工作线程和同步

4
我正在尝试编写一个简单的库,其中有一个后台工作线程,在调用库函数时处理命令。在C中,我通常会使用全局信号量句柄来阻塞工作线程。函数在发送命令后会释放信号量,此时工作线程会取消阻塞等等......还有其他方法,但这只是一个示例。
我有几个关于如何在Rust中实现类似功能的问题。
1. 如何防止线程在创建它的函数返回后关闭?例如,当我调用init()时将创建线程,但当init()返回时,该线程将退出,如何防止这种情况发生?
2. 如何在工作线程和函数调用之间进行全局同步?我正在考虑使用通道,但如何从线程中访问rx并从不同的函数中使用多个tx,例如将send_cmd_a()send_cmd_b()发送到同一线程?
以下是我想要完成的伪代码:
static (tx, rx) = mpsc::channel(); //how to do something like this?

fn init() {
    thread::spawn(|| {
        loop {
            let cmd = rx.recv().unwrap(); //blocks till there is data
                                          //process data....
            if cmd == "exit" {
                return;
            }
        }
    });
}

fn send_cmd_a() {
    //Do a bunch of other stuff...
    tx.send("cmd_a").unwrap();
}

fn exit() {
    tx.send("exit").unwrap();
}

我需要创建一个大对象来封装所有这些内容,从而拥有同步机制吗?(仍然不能回答问题#1)

在Rust中执行此类操作的首选方法是什么?


如何创建一个全局的、可变的单例? - Shepmaster
如何防止线程在创建它的函数返回后关闭,这已经是 thread::spawn 的行为了。 - Shepmaster
@Shepmaster 您是正确的。我搞错了,似乎线程仍然保持打开状态,但在程序退出时会自动关闭。此外,感谢您提供的链接。 - Marius
1个回答

3

我想我找到了一种用 Rust 实现我想要的功能的方法,而不需要使用全局变量。

struct Device {
    sender: Sender<u8>, //other stuff
}

trait New {
    fn new() -> Self;
}

trait SendCommand {
    fn send_command(&self, u8);
}

impl New for Device {
    fn new() -> Device {
        let (tx, rx) = channel();
        let device = Device { sender: tx };
        thread::spawn(move || {
            loop {
                let cmd = rx.recv().unwrap();
                println!("Command: {}", cmd); //process commands here
            }
        });
        return device;
    }
}

impl SendCommand for Device {
    fn send_command(&self, cmd: u8) {
        self.sender.send(cmd).unwrap();
    }
}

fn main() {
    let dev = Device::new(); //create the device
    for i in 0..10 {
        dev.send_command(i); //send commands
        sleep(Duration::from_millis(50));
    }
    loop {}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接