std::thread线程生命周期与线程对象生命周期的联系

1 介绍

在C++中,std::thread对象的生命周期与它所代表的线程的生命周期是紧密关联的,但它们并不完全相同

首先,当一个std::thread对象被创建时,它所代表的线程会立即开始执行。这一点体现了C++中即时执行的设计选择,旨在简化线程的创建和管理。这种设计减少了开发者的认知负荷,因为不需要额外的启动调用来开始线程的执行。

其次,std::thread对象遵循RAII(资源获取即初始化)原则,这意味着当std::thread对象被销毁时,它所代表的线程也会被终止。如果线程在std::thread对象销毁时仍在运行,那么程序的行为将是未定义的。因此,通常需要在线程对象的生命周期结束前,通过调用成员函数join或detach来适当地结束线程。

再者,std::thread对象是不可复制的,只具有移动属性。这是因为每个线程都有一个唯一的标识符,即线程ID,而复制一个std::thread对象将导致两个线程对象拥有同一个线程ID,这是不可能的。因此,std::thread对象只能通过移动构造函数或移动赋值操作符来转移所有权。

调用了detach()方法将该线程分离,使其在后台运行并自行结束。由于线程被分离后,其生命周期与线程对象的生命周期不再相关联,因此即使线程对象被销毁,线程本身仍然可以继续执行直到完成。

最后,需要注意的是,即使线程已经分离(detached)或者加入了(joined),std::thread对象的析构函数仍然会检查线程是否还在运行。如果是,它将调用std::terminate()来终止程序,除非线程已经被分离或者加入了。这是为了确保不会出现悬挂线程(orphan threads),即那些在std::thread对象销毁后仍在运行的线程。

综上所述,std::thread对象的生命周期通常决定了它所代表的线程的开始和结束,但它们并不是完全同步的。正确管理std::thread对象的生命周期对于避免程序错误和资源泄露至关重要。

2 示例

以下是使用Boost.Beast实现的WebSocket客户端和服务器的示例程序:

WebSocket客户端示例代码:

#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <iostream>
#include <string>

namespace beast = boost::beast;
namespace websocket = beast::websocket;
namespace net = boost::asio;
using tcp = net::ip::tcp;

int main(int argc, char* argv[]) {
    try {
        if (argc != 4) {
            std::cerr << "Usage: ws_client <host> <port> <message>" << std::endl;
            return EXIT_FAILURE;
        }

        auto const host = argv[1];
        auto const port = argv[2];
        auto const message = argv[3];

        net::io_context ioc;
        tcp::resolver resolver{ioc};
        websocket::stream<tcp::socket> ws{ioc};

        auto const results = resolver.resolve(host, port);
        net::connect(ws.next_layer(), results.begin(), results.end());

        ws.handshake(host, "/");
        ws.write(net::buffer(message));

        beast::flat_buffer buffer;
        ws.read(buffer);
        ws.close(websocket::close_code::normal);

        std::cout << "Received response: " << beast::make_printable(buffer.data()) << std::endl;
    } catch (std::exception const& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

WebSocket服务器示例代码:

#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/config.hpp>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <vector>

namespace beast = boost::beast;
namespace websocket = beast::websocket;
namespace net = boost::asio;
using tcp = net::ip::tcp;

void session(tcp::socket socket) {
    bool close = false;
    beast::error_code ec;

    websocket::stream<tcp::socket> ws{std::move(socket)};
    ws.accept(ec);
    if (ec) {
        std::cerr << "Error accepting connection: " << ec.message() << std::endl;
        return;
    }

    beast::flat_buffer buffer;
    ws.read(buffer);
    std::string message = beast::make_printable(buffer.data());
    std::cout << "Received message: " << message << std::endl;

    std::string response = "Hello, World!";
    ws.write(net::buffer(response), ec);
    if (ec) {
        std::cerr << "Error writing response: " << ec.message() << std::endl;
        return;
    }

    close = true;
    if (close) {
        ws.close(websocket::close_code::normal, ec);
    }
}

int main(int argc, char* argv[]) {
    try {
        if (argc != 3) {
            std::cerr << "Usage: ws_server <address> <port>" << std::endl;
            return EXIT_FAILURE;
        }

        auto const address = argv[1];
        auto const port = argv[2];

        net::io_context ioc{1};
        tcp::acceptor acceptor{ioc, {address, port}};
        tcp::socket socket{ioc};

        while (true) {
            acceptor.accept(socket, net::use_future);
            std::make_shared<std::thread>(std::bind(&session, std::move(socket)))->detach();
        }
    } catch (std::exception const& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值