我开始用网络做一个项目。但是在设置了std :: thread之后,while(true)-loop就不会启动了。
我做的第一件事就是设置正在侦听新客户端的std :: thread。在线程使用的函数是while(true)-loop,它完美地工作。在初始化serverListener std :: thread之后的主线程中,又是一个while(true)-loop尝试接收数据,但是这个循环不会启动,除非我在while循环之前放入一个std :: cout for-loop,但这会阻止我的控制台。
变量和包含:
#include <SFML/Network.hpp>
#include <iostream>
#include <list>
#include <thread>
#define PORT 1337
unsigned int clientCounter = 0;
sf::TcpSocket clients[5];
sf::Packet packet;
std :: thread使用的函数:
void serverListener() {
sf::TcpListener listener;
listener.listen(PORT);
while (true) {
if (listener.accept(clients[clientCounter]) == sf::Socket::Status::Done) {
std::cout << "New client connected: "
<< clients[clientCounter].getRemoteAddress() << std::endl;
clientCounter++;
}
}
}
主线程:
int main()
{
std::thread serverListenerThread(&serverListener);
while(true) {
//std::cout << "Some message"; <----- when uncomment, the loop works?
for (int i = 0; i < clientCounter; i++) {
std::string message = "";
packet >> message;
if (clients[i].receive(packet) == sf::Socket::Status::Done) {
message += std::to_string(i);
std::cout << message << std::endl;
}
}
}
return 0;
}
想一想第一个线程看到的内容。由于两个线程之间没有同步,编译器假定它们不通信,因此在执行内部for循环时,clientCounter
的值永远不会改变。因此循环将始终看到clientCounter=0
,因此循环不会运行。
unsigned int clientCounter = 0;
int main()
{
std::thread serverListenerThread(&serverListener);
while(true) {
for (int i = 0; i < clientCounter; i++) {
// Never executed, since clientCounter = 0
}
}
}
你应该使clientCounter
成为std::atomic<unsigned int>
。这使编译器知道在线程之间同步变量。通常,线程之间共享的任何内容都应该是原子的,或者应该通过锁定互斥锁来保护。
增加睡眠可能有所帮助,但只能靠纯粹的运气;绝对没有理由继续工作。特别是,没有要求在while循环迭代之间从内存中加载clientCounter
的值,因为编译器“知道”它永远不会写入主线程中。因此,重新加载它将是多余的。