我写了一个网络记录器,它在单独的线程中工作。我们的想法是允许应用程序推送任何数量的数据,并且记录器应该单独处理它而不会减慢主线程的速度。伪代码看起来像:
void LogCoroutine::runLogic()
{
mBackgroundWorker = std::thread(&LogCoroutine::logic, this);
mBackgroundWorker.detach();
}
void LogCoroutine::logic()
{
while (true)
{
_serverLogic();
_senderLogic();
std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 10ms
}
}
void LogCoroutine::_senderLogic()
{
std::lock_guard<std::mutex> lock(mMutex);
while (!mMessages.empty() && !mClients.empty())
{
std::string nextMessage = mMessages.front();
mMessages.pop_front();
_sendMessage(nextMessage);
}
}
_serverLogic
检查套接字是否有新连接(对等体)和_senderLogic
进程与消息队列,并将其发送给所有连接的对等体。
最后一个功能:推送消息:
void LogCoroutine::pushMessage(const std::string& message)
{
std::lock_guard<std::mutex> lock(mMutex);
mMessages.push_back(message);
}
当包裹不经常发送时,一切都很顺利。应用程序启动时会有一个循环记录大量信息。应用程序挂起5-10秒,没有记录它不会减慢速度。
那么,这个架构的瓶颈在哪里?也许用内置互斥锁推送每条消息是一个坏主意?
答案 0 :(得分:1)
您的方法基本上是以一定间隔(10毫秒)轮询日志事件。这种方法(实际上忙于等待)不是很有效,因为即使没有任何日志消息,您也总是消耗一些CPU。另一方面,如果新消息到达,则不通知等待线程。
我建议使用某种blocking queue来解决这两个问题。内部阻塞队列具有互斥和条件变量,因此当队列为空时,消费者线程正在等待(不忙循环!)。我认为你的用例非常适合阻塞队列。您可以基于互斥+条件变量轻松实现自己的队列。
使用互斥锁推送每条消息并不是一个坏主意,无论如何都必须同步它。我只是建议摆脱民意调查。
答案 1 :(得分:0)
See this example: 如何为生产者和工作队使用工作队列消费者(1对多)。很好地解释了。