为什么在std :: thread启动后我的while循环不启动?

时间:2019-04-30 14:55:32

标签: c++ sfml

我已经开始做一个网络项目。但是在设置了std :: thread之后,while(true)循环将不会启动。

我要做的第一件事是设置正在侦听新客户端的std :: thread。在线程使用的函数中有一个while(true)循环,可以完美地工作。在初始化serverListener std :: thread之后的主线程中,再次是一个while(true)循环,尝试接收数据,但是该循环不会启动,除非当我在之前的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;
}

1 个答案:

答案 0 :(得分:1)

请稍等一下第一个线程所看到的内容。由于您在两个线程之间没有同步,因此编译器会假定它们不通信,因此在执行内部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的值,因为编译器“知道”它永远不会写入主线程。因此,重新加载将是多余的。