concurrency - 如何使用 Condvar 和 Mutex 监控变化

标签 concurrency locking rust race-condition wakeup

我有一个共享 Vec<CacheChange> .每当一个新的CacheChange写的我想唤醒读者。我记得一个Condvar有利于在谓词/情况准备就绪时发出信号,即当 Vec 时已修改。

所以我花了一些时间创建了一个 Monitor拥有 Vec 的抽象并提供waitlock语义。

现在的问题是我不知道什么时候重置Condvar .给读者合理的时间来命中谓词并努力持有锁的好方法是什么?在关闭 condvar 之前?我接近Condvar走错路了吗?

这是 Rust 代码,但这更多的是关于多个读者之间精确并发访问/通知的基础问题。

pub struct Monitor<T>(
    sync::Arc<MonitorInner<T>>
);

struct MonitorInner<T> {
    data: sync::Mutex<T>,
    predicate: (sync::Mutex<bool>, sync::Condvar)
}

impl<T> Monitor<T> {   
    pub fn wait(&self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>> {
        let mut open = try!(self.0.predicate.0.lock());
        while !*open {
            open = try!(self.0.predicate.1.wait(open));
        }
        Ok(())
    }

    pub fn lock(&self) -> Result<sync::MutexGuard<T>, sync::PoisonError<sync::MutexGuard<T>>> {
        self.0.data.lock()
    }

    pub fn reset(&mut self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>> {
        let mut open = try!(self.0.predicate.0.lock());
        *open = false;
        Ok(())
    }

    pub fn wakeup_all(&mut self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>>  {
        let mut open = try!(self.0.predicate.0.lock());
        *open = true;
        self.0.predicate.1.notify_all();
        Ok(())
    }
}

在第一次叫醒电话后,我的读者可能会错过阅读。可能是因为当谓词再次切换时它们仍然持有数据锁。我在我的测试代码中看到了这一点,只有一个读者和一个作者。

然后是何时重置 Monitor 的复杂问题, 理想情况下,在所有读者都有机会查看数据后,它会被锁定。如果读者忽略他们的监视器(不保证他们应该为每个唤醒调用服务),这可能会导致死锁问题。

我是否需要使用某种具有超时功能的读者跟踪系统,并在新数据到达时跟踪监视器读取仍在服务中?是否有我应该注意的现有范例?

最佳答案

最简单的解决方案是使用计数器而不是 bool 值。

struct MonitorInner<T> {
    data: sync::Mutex<T>,
    signal: sync::Condvar,
    counter: sync::AtomicUsize,
}

然后,每次更新完成时,计数器都会递增。它从不重置,因此不存在何时重置的问题。

当然,这意味着读者应该记住上次被唤醒时计数器的值。

关于concurrency - 如何使用 Condvar 和 Mutex 监控变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40254677/

相关文章:

java - Servlet 似乎同步处理多个并发浏览器请求

java - 下面的代码是线程安全的吗?

c++ - 使用 std::atomic<T*> 作为围栏

windows - 处理 .net 核心中的窗口锁定/解锁事件

iterator - 如果另一个特征是否实现,函数如何有条件地回退到特征?

Python线程,Event和Queue如何协同工作?

git - .git/index.lock 文件实际上做了什么?

linux - flock 和 NFS——意外关机时会发生什么?

parallel-processing - 为什么基于人造丝的并行处理比串行处理需要更多时间?

rust - 在多个函数中使用String的问题