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

问题描述 投票:0回答:1

我开始用网络做一个项目。但是在设置了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;
}
c++ sfml
1个回答
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的值,因为编译器“知道”它永远不会写入主线程中。因此,重新加载它将是多余的。

© www.soinside.com 2019 - 2024. All rights reserved.