multithreading - 将堆栈数据传入和传出闭包

标签 multithreading synchronization thread-safety rust

我有一个 C 函数,由于各种 C 原因,它只能从某些类型的线程中调用。我正在尝试从 Rust 调用此函数。

我的想法是将输入数据传送到“正确的”线程,在该线程上调用 C 函数,然后在将其返回值传送回之前使用信号量在线程上等待。

线程不用于并发;这实际上是一个相当同步的执行流程。只是 C 函数对如何使用它很挑剔。

这是我的尝试:

use std::thread::Thread;

struct Foo {
    x: std::sync::Semaphore,
}

//Not the real C function, of course.
fn my_great_c_function(i: i32) -> i32 {
    println!("{}",i);
    return 12;
}

impl Foo {
    fn bar(&self) {
        self.x = std::sync::Semaphore::new(0);
        let input : i32 = 5;
        let mut output : i32 = 10;
        Thread::spawn(|:| {
            //call out to our C function that only likes some threads
            output = my_great_c_function(input);
            self.x.release(); //our work is done; the parent thread can continue
        });
        self.x.acquire(); //wait for child thread to be done interacting with environment
        println!("{}",input); //check input
        println!("{}",output); //check output
    }

}

Rust 编译器输出整页错误,解释它由于需求冲突无法推断出合适的生命周期

据我所知,我认为编译器担心闭包可能比堆栈帧还长,闭包对 inputoutput 的引用可能会被吹走而闭包仍在使用它们(我怀疑,这就是 lifetime parameter must outlive the static lifetime 的含义)。但实际上,信号量用于在闭包完成之前保持堆栈帧处于事件状态,因此不应该发生这种情况。

有没有办法让编译器平静下来?有没有其他方法可以解决这个问题?

最佳答案

Thread::spawn是这样定义的:

fn spawn<F>(f: F) -> Thread where F: FnOnce(), F: Send + 'static

您传递给它的函数必须拥有它的所有数据('static 要求如此)。但是,您正在尝试使用 self 做一些绝对不是 'static 的事情。请记住,Rust 关心安全;不允许线程干扰其他线程的数据:您不能在多个线程上访问一个对象。

您想要的实际上比您尝试的更容易:使用 Thread::scoped :

impl Foo {
    fn bar(&self) {
        let input = 5i32;
        let output = Thread::scoped(|:| {
            my_great_c_function(input)
        }).join().unwrap();
        println!("{}", input);
        println!("{}", output);
    }
}

关于multithreading - 将堆栈数据传入和传出闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28184317/

相关文章:

java - 从 EDU 迁移到 java.util.concurrent 会降低性能两倍

java - 尝试在不使用 Java 中的任何库的情况下解决竞争条件

c# - 下面类线程安全吗?解释

multithreading - 子线程看不到主线程所做的更新

multithreading - Scala - 可变线程安全集合

java - Java等待方法的工作原理

go - 不明显的死锁情况

android - 什么是更新 RecyclerView 中大量移动的项目(交换)和即时用户反馈的良好实现?

go - sync.Cond 测试广播 - 为什么要循环检查?

java - 将本地新对象传递给线程,线程安全吗?