c++ - 在异步 TCP 服务器的上下文中从 N-theads 访问数据时的线程安全

标签 c++ multithreading boost-asio

正如标题所说,我有一个关于以下场景的问题(简单示例):

假设我有一个下面的生成器类的对象,它不断更新它的 dataChunk 成员(在主线程中运行)。

class Generator
{
  void generateData();
  uint8_t dataChunk[999];
}

此外,我有一个异步。 1-N 客户端可以连接到的 TCP 连接的接受器(在第二个线程中运行)。 接受器为每个新的客户端连接启动一个新线程,其中下面的 Connection 类的对象从客户端接收请求消息,并提供 dataChunk 的一部分(属于生成器)作为答案。然后等待新的请求等等……

class Connection
{

  void setDataChunk(uint8_t* dataChunk);
  void handleRequest();
  uint8_t* dataChunk;
}

最后是真正的问题:期望的行为是 Generator 对象生成一个新的 dataChunk 并等待直到所有 1-N Connection 对象都处理完它们的客户端请求,直到它生成一个新的 dataChunk。

当 Connection 对象处理它们的请求时,我如何锁定 dataChunk 以便对 Generator 对象进行写访问,但是在它们的请求处理阶段,它们各自线程中的所有 Connection 对象都应该同时具有读访问权限.

另一方面,连接对象应该在处理完各自的请求后等待新的数据 block ,而不会丢弃新的客户端请求。

--> 我认为单个互斥体在这里不起作用。

我的第一个想法是在对象之间共享一个结构,其中一个信号量用于生成器,一个信号量 vector 用于连接。有了这些,每个对象都可以“理解”整个系统的状态并相应地工作。

你们怎么看,在这种情况下,最佳实践是什么?

提前致谢!

最佳答案

有几种方法可以解决。

您可以使用 std::shared_mutex

void Connection::handleRequest()
{
    while(true)
    {
        std::shared_lock<std::shared_mutex> lock(GeneratorObj.shared_mutex);
        if(GeneratorObj.DataIsAvailable()) // we need to know that data is available
        {
            // Send to client
            break;
        }
    }
}

void Generator::generateData()
{
    std::unique_lock<std::shared_mutex> lock(GeneratorObj.shared_mutex);

    // Generate data
}

或者您可以使用 boost::lockfree::queue,但数据结构会有所不同。

关于c++ - 在异步 TCP 服务器的上下文中从 N-theads 访问数据时的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50304403/

相关文章:

c++ - 有没有办法与其他循环条件一起使用 erase-remove 习语?

.net - 杀死线程后如何分配内存?

multithreading - Nodejs中的单线程是什么意思

c++ - 系统的boost::asio无限循环:第一次连接后出现9错误

c++ - boost asio SSL双向身份验证

c++ - `deadline_timer`中 `waitable_timer`和 `boost asio`的区别

c++ - 函数指针的函数模板特化

c++ - C++ 11的序列压缩函数?

C++ 迭代器和链表

c - 使用 pthreads 在客户端-服务器设置中终止客户端线程