为什么在 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' 它永远不会在主线程中写入。因此,重新加载它是多余的。