Rust 如何创建具有两个condvar的互斥体?
我想在Rust中构建一个单生产者多消费者的示例,其中生产者的未完成项目不得超过10个。我用C建模了一个解决方案,它使用一个互斥锁和两个condvar。一个condvar是在没有东西可消费时等待消费者,另一个condvar是在未消费项计数大于10时等待生产者。下面是C代码 正如我从Rust文档中了解到的,在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:
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();
}