如何创建线程安全缓冲区/ POD?

时间:2015-04-25 21:37:28

标签: c++ multithreading c++11

我认为我的问题很常见,但它让我发疯:

我有一个包含5个线程的多线程应用程序。其中4个线程完成它们的工作,比如网络通信和本地文件系统访问,然后所有线程都将它们的输出写入这种形式的数据结构:

struct Buffer {
  std::vector<std::string> lines;
  bool has_been_modified;
}

第5个线程将​​这些缓冲区/结构打印到屏幕上:

Buffer buf1, buf2, buf3, buf4;

...

if ( buf1.has_been_modified || 
     buf2.has_been_modified || 
     buf3.has_been_modified || 
     buf4.has_been_modified )
{
  redraw_screen_from_buffers();
}

如何保护缓冲区在被读取或写入时不会被覆盖?

我无法找到合适的解决方案,但我认为这必须是一个安静的常见问题。

感谢。

4 个答案:

答案 0 :(得分:10)

您应该使用互斥锁。互斥类为 <Page.BottomAppBar> <CommandBar IsTabStop="False" ClosedDisplayMode="Minimal"> <!-- Buttons --> </CommandBar> </Page.BottomAppBar> 。使用C ++ 11,您可以使用std::mutex使用RAII封装互斥锁。因此,您可以将std::lock_guard<std::mutex>结构更改为

Buffer

每当您读取或写入缓冲区或struct Buffer { std::vector<std::string> lines; bool has_been_modified; std::mutex mutex; }; 时,您都会

has_been_modified

并且当std::lock_guard<std::mutex> lockGuard(Buffer.mutex); //Do this for each buffer you want to access ... //Access buffer here 被销毁时,互斥锁将自动释放。

您可以阅读有关互斥锁here的更多信息。

答案 1 :(得分:5)

您可以在缓冲区周围使用互斥锁(或互斥锁),以确保它们不会被多个线程同时修改。

// Mutex shared between the multiple threads
std::mutex g_BufferMutex;

void redraw_screen_from_buffers()
{
   std::lock_guard<std::mutex> bufferLockGuard(g_BufferMutex);
   //redraw here after mutex has been locked.
}

然后,在修改缓冲区时,您的缓冲区修改代码必须锁定相同的互斥锁。

void updateBuffer()
{
   std::lock_guard<std::mutex> bufferLockGuard(g_BufferMutex);
   // update here after mutex has been locked
}

This包含一些互斥示例。

答案 2 :(得分:3)

您想要完成的是拥有多个线程/工作人员和一个观察者。后者只有在所有工人完成/发出信号后才能完成工作。如果是这种情况,则检查此SO q / a中的代码。 std::condition_variable - Wait for several threads to notify observer

答案 3 :(得分:2)

在尝试避免数据集时,互斥是一件非常好的事情,我确信@Phantom发布的答案将满足大多数人的需求。但是,应该知道这不适用于大型系统。

通过锁定,您正在同步线程。因为只有一个一次可以访问向量,在线程写入容器将导致另一个等待它完成...可能对你有好处,但是当需要高性能时会导致严重的性能。 / p>

最好的解决方案是使用更复杂的无锁结构。不幸的是,我认为STL中没有任何标准的无锁结构。可以使用无锁队列的一个例子here

使用这样的结构,你的4个工作线程将能够将消息排入容器,而第5个将使它们出列,而没有任何数据集

More on lockfree datastructure can be found here !