正如标题所说,我有一个关于以下场景的问题(简单示例):
假设我有一个下面的生成器类的对象,它不断更新它的 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/