Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 如何创建具有两个condvar的互斥体?_Rust_Mutex_Condition Variable - Fatal编程技术网

Rust 如何创建具有两个condvar的互斥体?

Rust 如何创建具有两个condvar的互斥体?,rust,mutex,condition-variable,Rust,Mutex,Condition Variable,我想在Rust中构建一个单生产者多消费者的示例,其中生产者的未完成项目不得超过10个。我用C建模了一个解决方案,它使用一个互斥锁和两个condvar。一个condvar是在没有东西可消费时等待消费者,另一个condvar是在未消费项计数大于10时等待生产者。下面是C代码 正如我从Rust文档中了解到的,在std::sync::Mutex和std::sync::Condvar之间必须存在1-1连接,因此我无法对我的C解决方案进行精确的翻译 使用std::sync::Mutex和std::sync:

我想在Rust中构建一个单生产者多消费者的示例,其中生产者的未完成项目不得超过10个。我用C建模了一个解决方案,它使用一个互斥锁和两个condvar。一个condvar是在没有东西可消费时等待消费者,另一个condvar是在未消费项计数大于10时等待生产者。下面是C代码

正如我从Rust文档中了解到的,在
std::sync::Mutex
std::sync::Condvar
之间必须存在1-1连接,因此我无法对我的C解决方案进行精确的翻译

使用
std::sync::Mutex
std::sync::Condvar
是否有其他方法可以达到Rust中的相同目的(我看不到)

定义GNU源
#包括
#包括
#包括
#包括
#包括
//
//这是一个使用互斥锁和2个条件变量
//同步与有界(固定最大大小)队列交互的单个写入程序和多个读取程序
//
//在本例中,队列由int计数器n_资源模拟
//
国际自然资源;
pthread_cond_t rdr_cvar;
pthread_cond_t wrtr_cvar;
pthread_mutex_t mutex;
无效读取器(无效*数据)
{
长id=(长)数据;
对于(;;){
pthread_mutex_lock(&mutex);
while(n_资源0){
pthread_cond_信号(&rdr_cvar);
}
//如果有空间供写入程序添加另一个信号,则写入程序
如果(n_资源<10){
pthread_cond_信号(&wrtr_cvar);
}
pthread_mutex_unlock(&mutex);
}
}
无效写入程序(无效*数据)
{
对于(;;){
pthread_mutex_lock(&mutex);
printf(“写入程序在n\u资源%d\n之前”,n\u资源);
而(n_资源>10){
pthread_cond_wait(&wrtr_cvar,&mutex);
}
printf(“写入程序在n\u资源%d\n之后”,n\u资源);
++n_资源;
//如果某个读卡器需要读取某些内容,则向其中一个读卡器发送信号。
如果(n_资源>0){
pthread_cond_信号(&rdr_cvar);
}
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t rdr_thread_1;
pthread_t rdr_thread_2;
pthread_t wrtr_螺纹;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&rdr_cvar,NULL);
pthread_cond_init(&wrtr_cvar,NULL);
pthread_create(&rdr_thread_1,NULL,&reader,(void*)1L);
pthread_create(&rdr_thread_2,NULL,&reader,(void*)2L);
pthread_create(&wrtr_thread,NULL,&writer,NULL);
pthread_join(wrtr_thread,NULL);
pthread_join(rdr_thread_1,NULL);
pthread_join(rdr_thread_2,NULL);
}

虽然
CondVar
只需要与一个
互斥体关联,但
互斥体
不一定只与一个
CondVar
关联

例如,下面的代码似乎工作得很好-您可以在上运行它

使用std::sync::{Arc、Condvar、Mutex};
使用std::线程;
结构Q{
rdr_cvar:Condvar,
wrtr_cvar:Condvar,
互斥体:互斥体,
}
implq{
pub fn new()->Q{
Q{
rdr_cvar:Condvar::new(),
wrtr_cvar:Condvar::new(),
互斥体:互斥体::新建(0),
}
}
}
fn编写器(id:i32,qq:Arc){
设q=&*qq;
因为我在0..10{
让guard=q.mutex.lock().unwrap();
让mut guard=q.wrtr_cvar.稍等片刻(guard,| n |*n>3)。展开();
println!(“{}:Writer{}n_resource={}\n”,i,id,*guard);
*防护装置+=1;
如果*guard>0{
q、 rdr_cvar.notify_one();
}
如果*防护<10{
q、 请通知我一个人;
}
}
}
fn阅读器(id:i32,qq:Arc){
设q=&*qq;
因为我在0..10{
让guard=q.mutex.lock().unwrap();
让mut guard=q.rdr_cvar.稍等片刻(guard,| n |*n0{
q、 rdr_cvar.notify_one();
}
如果*防护<10{
q、 请通知我一个人;
}
}
}
fn main(){
让data=Arc::new(Q::new());
让data2=data.clone();
设t1=thread::spawn(移动| | writer(0,data2));
让t2=thread::spawn(移动| |读取器(1,数据));
t1.join().unwrap();
t2.连接().展开();
}

虽然
CondVar
只需要与一个
互斥体关联,但
互斥体
不一定只与一个
CondVar
关联

例如,下面的代码似乎工作得很好-您可以在上运行它

使用std::sync::{Arc、Condvar、Mutex};
使用std::线程;
结构Q{
rdr_cvar:Condvar,
wrtr_cvar:Condvar,
互斥体:互斥体,
}
implq{
pub fn new()->Q{
Q{
rdr_cvar:Condvar::new(),
wrtr_cvar:Condvar::new(),
互斥体:互斥体::新建(0),
}
}
}
fn编写器(id:i32,qq:Arc){
设q=&*qq;
因为我在0..10{
让guard=q.mutex.lock().unwrap();
让mut guard=q.wrtr_cvar.稍等片刻(guard,| n |*n>3)。展开();
println!(“{}:Writer{}n_resource={}\n”,i,id,*guard);
*防护装置+=1;
如果*guard>0{
q、 rdr_cvar.notify_one();
}
如果*防护<10{
q、 请通知我一个人;
}
}
}
fn阅读器(id:i32,qq:Arc){
设q=&*qq;
因为我在0..10{
让guard=q.mutex.lock().unwrap();
让mut guard=q.rdr_cvar.稍等片刻(guard,| n |*n0{
q、 rdr_cvar.notify_one();
}
如果*防护<10{
q、 请通知我一个人;
}
}
}
fn main(){
让data=Arc::new(Q::new());
让data2=data.clone();
设t1=thread::spawn(移动| | writer(0,data2));
让t2=thread::spawn(移动| |读取器(1,数据));
t1.join().unwrap();
t2.连接().展开();
}

您的问题似乎可以通过以下答案来回答:使用两个
Condvar
s和一个
Mutex
use std::sync::{Arc, Condvar, Mutex};
use std::thread;

struct Q {
    rdr_cvar: Condvar,
    wrtr_cvar: Condvar,
    mutex: Mutex<i32>,
}

impl Q {
    pub fn new() -> Q {
        Q {
            rdr_cvar: Condvar::new(),
            wrtr_cvar: Condvar::new(),
            mutex: Mutex::new(0),
        }
    }
}

fn writer(id: i32, qq: Arc<Q>) {
    let q = &*qq;
    for i in 0..10 {
        let guard = q.mutex.lock().unwrap();
        let mut guard = q.wrtr_cvar.wait_while(guard, |n| *n > 3).unwrap();

        println!("{}: Writer {} n_resource = {}\n", i, id, *guard);
        *guard += 1;

        if *guard > 0 {
            q.rdr_cvar.notify_one();
        }
        if *guard < 10 {
            q.wrtr_cvar.notify_one();
        }
    }
}

fn reader(id: i32, qq: Arc<Q>) {
    let q = &*qq;
    for i in 0..10 {
        let guard = q.mutex.lock().unwrap();
        let mut guard = q.rdr_cvar.wait_while(guard, |n| *n <= 0).unwrap();

        println!("{} Reader {} n_resource = {}\n", i, id, *guard);
        *guard -= 1;

        if *guard > 0 {
            q.rdr_cvar.notify_one();
        }
        if *guard < 10 {
            q.wrtr_cvar.notify_one();
        }
    }
}

fn main() {
    let data = Arc::new(Q::new());
    let data2 = data.clone();

    let t1 = thread::spawn(move || writer(0, data2));
    let t2 = thread::spawn(move || reader(1, data));

    t1.join().unwrap();
    t2.join().unwrap();
}