gpt4 book ai didi

c++ - 何时使用 C++ 类锁定互斥体

转载 作者:太空宇宙 更新时间:2023-11-04 11:44:34 26 4
gpt4 key购买 nike

我目前正在开发一个接受多个客户端的服务器。

在服务器端,我有一个线程池(手工制作,工作正常),用于午餐多个线程:

ThreadPool::bind(new TCPReceiver());
ThreadPool::bind(new TCPSender());

一旦一个类被绑定(bind)到ThreadPool,它的start()函数就会被调用。

基本上我的服务器所做的是:

  • 绑定(bind)线程
  • 接受一个或多个客户
  • 将客户端的指针添加到 TCPReceiver 客户端列表
    • TCPReceiver执行socket.receive(),将接收到的数据推送给消息队列中的Client
  • 将客户端的指针添加到 TCPSender 客户端列表
    • TCPSender执行socket.send()并发送Client的输出消息队列

因此,一旦连接了客户端,其类的指针就会附加到 2 个线程,一个读取套接字,一个在套接字上发送。同时,主线程(服务器)弹出客户端的输入消息队列。

class Server {
std::list<Client*> clients;

TCPReceiver receive;
TCPSender send;

public:
void *start();
}

class Client {
std::list<NetworkMessage*> inQueue;
IMutex *inMutex;

std::list<NetworkMessage*> outQueue;
IMutex *outMutex;

Socket *socket;
}

class TCPReceiver {
std::list<Client*> clients;

public:
void *start();
}

class TCPSender {
std::list<Client*> clients;

public:
void *start();
}

我的问题是:

从 Server/TCPReceiver/TCPSender 类,我可以在不锁定 Client 类的情况下访问/使用 Client 指针,但只锁定 Client 的消息队列以弹出/推送它吗?

2个线程可以同时调用不同Client的成员函数吗?

我可以在不锁定 std::list 的情况下调用 std::list 的成员函数吗(参见 (*it)->inQueue.empty() 调用)?

void Server::start() {
for (std::list<Client*>::iterator it = this->clients.begin(); it != this->clients.end(); ++it) {
if (!(*it)->inQueue.empty()) {
(*it)->inMutex->lock();
(*it)->inQueue.front();
(*it)->inQueue.pop_front();
(*it)->inMutex->unlock();
}
}
}

同时在 TCPReceiver 上:

void TCPReceiver::start() {
for (std::list<Client*>::iterator it = this->clients.begin(); it != this->clients.end(); ++it) {
std::string msg = (*it)->socket->receive();
if (!msg.empty()){
(*it)->inMutex->lock();
(*it)->inQueue.push_back(msg);
(*it)->inMutex->unlock();
}
}
}

(我知道套接字也应该有一个互斥体,但这不是我现在想要理解的)

最佳答案

是的,两个线程确实可以同时执行同一个实例的方法。您需要某种同步机制来防止由于同时修改相同的值而导致的竞争条件。在这方面,读取的危险性不亚于写入,因为在进行写入操作时读取可能会导致读取垃圾值。

基本上,这意味着您应该在检查队列是否为空之前锁定,(因为您的线程可能在该行和下一行之间挂起),但您不需要锁定在循环之外对客户端进行迭代,前提是保证客户端列表在迭代期间不会更改。

您需要确保没有线程访问处于无效状态的任何对象。对于您所描述的那种生产者-消费者情况,您可能有兴趣了解 condition variables。 ,它提供了一种等待某些状态改变的方法。 (例如,等待空队列不再为空)。

请注意,在您提供的示例中,您只循环遍历 clients 一次,并且最多向每个队列添加/删除一条消息。

关于c++ - 何时使用 C++ 类锁定互斥体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20193417/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com