为什么在 std::thread 启动后我的 while 循环没有启动?
Why isn't my while-loop starting after the std::thread is started?
我已经开始做一个网络项目。但是在设置 std::thread 之后,while(true)-loop 不会启动。
我做的第一件事是设置 std::thread 来监听新客户。在线程使用的函数中有一个 while(true) 循环,它运行良好。在初始化 serverListener std::thread 后的主线程中,再次是一个 while(true)-loop,它试图接收数据,但是这个循环不会开始,除非我在 while- 中放置一个 std::cout在 for 循环之前循环,但这会向我的控制台发送垃圾邮件。
变量和包含物:
#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;
}
想一想第一个线程看到的内容。由于两个线程之间没有同步,编译器假定它们不通信,因此 clientCounter
的值在执行内部 for 循环时永远不会改变。因此循环将始终看到 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
的值,因为编译器 'knows' 它永远不会在主线程中写入。因此,重新加载它是多余的。
我已经开始做一个网络项目。但是在设置 std::thread 之后,while(true)-loop 不会启动。
我做的第一件事是设置 std::thread 来监听新客户。在线程使用的函数中有一个 while(true) 循环,它运行良好。在初始化 serverListener std::thread 后的主线程中,再次是一个 while(true)-loop,它试图接收数据,但是这个循环不会开始,除非我在 while- 中放置一个 std::cout在 for 循环之前循环,但这会向我的控制台发送垃圾邮件。
变量和包含物:
#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;
}
想一想第一个线程看到的内容。由于两个线程之间没有同步,编译器假定它们不通信,因此 clientCounter
的值在执行内部 for 循环时永远不会改变。因此循环将始终看到 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
的值,因为编译器 'knows' 它永远不会在主线程中写入。因此,重新加载它是多余的。