4

我们有一个多线程应用程序。在当前实现中,thread1在启动时创建并定期(每秒左右,可配置)唤醒以检查磁盘是否有可能保存的文件。这些文件由另一个线程thread2保存。正在运行的thread1及其定期唤醒可能会减慢应用程序的速度。

现在我们有机会使用 boost::condition 变量将thread1阻塞,直到thread2通知它。通过这样做,需要创建一个标志以避免来自thread2的不必要通知,并且该标志需要同步并由thread2以高频率(几秒钟内数百次)检查。或者每次写入发生时都会通知thread1 。

我的问题如下:

  1. 在 boost::condition 实现中,thread1仍然需要频繁唤醒以检查标志,不同之处在于实现对我们隐藏,但它确实做到了。我对吗?Windows 和 Java 中的类似 API 做同样的事情?

  2. 如果一个线程即使不是处于等待状态,也经常被多次通知会发生什么?

  3. 就我而言,它会通过切换到 boost::condition 实现来提高整体性能?我的意见是不。

4

2 回答 2

1
  1. 在 POSIX 和 Win32 中, boost::condition 是使用基于事件的 API 实现的。从技术上讲,线程在收到事件之前不会唤醒。
  2. 如果在发送信号后线程进入等待状态 - 信号将丢失。您应该阅读有关实现“生产者/消费者”的基于事件的模式和策略。您的文件写入/读取示例是经典的生产者/消费者实例。为了避免丢失信号,请类似于 Wikipedia 中的 C++11 示例来实现它:http ://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem#Example_in_C.2B.2B

这个想法是如果 thread1 不等待条件,它将始终锁定共享互斥锁:

//thread1 - consumer
void thread1() {
    boost::scoped_lock lock(sharedMutex);
    // shared mutex locked, no events can be sent now
    while(1) {
        // check for files written by thread2
        sharedCond.wait( lock ); // this action unlocks the shared mutex, events can be sent now
    }
}

//thread2 - producer
void thread2() {
    boost::scoped_lock lock(sharedMutex); // will wait here until thread 1 starts waiting
    // write files
    sharedCond.notify_one();
}

3.性能问题:这个变化不是关于性能,而是将轮询改为事件模型。如果您的线程 1 每 1 秒唤醒一次,则切换到事件模型不会改善 CPU 或 I/O 负载(消除每 1 秒一次的文件验证),直到您在频率为几 KHz 且 I/O 操作阻塞的嵌入式系统中运行整个过程。它将提高线程 1 的反应时间,在轮询模式下,文件更改的最大响应时间为 1 秒,切换到事件后将立即采取行动。另一方面,线程 2 的性能可能会在事件模型中下降——在它没有等待任何东西之前,如果它使用条件——它必须锁定共享互斥体,这可能在线程 1 读取文件时一直被锁定。

于 2013-10-02T17:25:40.667 回答
0

高频检查标志正是 boost::condition 允许您避免的。thread1()只是等待flag被设置:

#include <mutex>
#include <condition_variable>
#include <thread>

std::mutex mut;
bool flag;
std::condition_variable data_cond;

void thread2()
{
    //here, writing to a file
    std::lock_guard<std::mutex> lk(mut);
    flag = true;  //a new file is saved
    data_cond.notify_one();
}

void thread1()
{
    while(true)
    {
        std::unique_lock<std::mutex> lk(mut);
        data_cond.wait(lk,[]{return flag;});
        //here, processing the file
        flag = false;
        lk.unlock();
    }
}

这是基于清单 4_1 中的 C++11 代码:C++ Concurrency in Action,第 4 章同步并发操作

于 2013-10-03T06:51:34.300 回答