拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 对于condition_variables有什么更好的

对于condition_variables有什么更好的

白鹭 - 2022-03-03 2081 0 0

我正在尝试制作一个多执行绪函式,它看起来像:

namespace {  // Anonymous namespace instead of static functions.

std::mutex log_mutex;

void Background() {
    while(IsAlive){
        std::queue<std::string> log_records;
        {
            // Exchange data for minimizing lock time.
            std::unique_lock lock(log_mutex);
            logs.swap(log_records);
        }
        if (log_records.empty()) {
            Sleep(200);
            continue;
        }
        while(!log_records.empty()){
            ShowLog(log_records.front()); 
            log_records.pop();
        }
    }
}

void Log(std::string log){
    std::unique_lock lock(log_mutex);
    logs.push(std::move(log));
}

}

即使日志为空,我也会使用 Sleep 来防止由于连续回圈而导致 CPU 使用率过高。但这有一个非常明显的缺点,它将批量打印日志。我试图通过使用条件变量来解决这个问题,但问题是如果在短时间内有太多日志,那么 cv 会停止并多次唤醒,导致 CPU 使用率更高。现在我能做些什么来解决这个问题?您可以假设每秒可能有很多呼叫记录。

uj5u.com热心网友回复:

我可能会考虑为此使用计数信号量:

  • 信号量将记录日志中的讯息数(最初为零)。
  • 日志客户端将写入一条讯息并通过释放信号量将讯息数量增加一。
  • 日志服务器将对信号量进行获取,阻塞直到日志中有任何讯息,然后将讯息数量减一。

注意:

  • 日志客户端获得logs队列锁,推送讯息,然后才对信号量进行释放。
  • 日志服务器可以在获取logs队列锁之前进行获取即使有更多的读者,这也是可能的。例如:日志队列中有 1 条讯息,服务器 1 进行获取,服务器 2 进行获取并阻塞,因为信号量计数为 0,服务器 1 继续并获取logs队列锁......
#include <algorithm>  // for_each
#include <chrono>  // chrono_literasl
#include <future>  // async, future
#include <iostream>  // cout
#include <mutex>  // mutex, unique_lock
#include <queue>
#include <semaphore>  // counting_semaphore
#include <string>
#include <thread>  // sleep_for
#include <vector>

std::mutex mtx{};
std::queue<std::string> logs{};
std::counting_semaphore c_semaphore{ 0 };

int main()
{
    auto log = [](std::string message) {
        std::unique_lock lock{ mtx };
        logs.push(std::move(message));
        c_semaphore.release();
    };
    auto log_client = [&log]() {
        using namespace std::chrono_literals;
        static size_t s_id{ 1 };
        size_t id{ s_id   };
        for (;;)
        {
            log(std::to_string(id));
            std::this_thread::sleep_for(id * 100ms);
        }
    };
    auto log_server = []() {
        for (;;)
        {
            c_semaphore.acquire();
            std::unique_lock lock{ mtx };
            std::cout << logs.front() << " ";
            logs.pop();
        }
    };

    std::vector<std::future<void>> log_clients(10);
    std::for_each(std::begin(log_clients), std::end(log_clients),
        [&log_client](auto& lc_fut) {
            lc_fut = std::async(std::launch::async, log_client);
        });
    auto ls_fut{ std::async(std::launch::async, log_server) };

    std::for_each(std::begin(log_clients), std::end(log_clients),
        [](auto& lc_fut) { lc_fut.wait(); });
    ls_fut.wait();
}
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *