【C++并发编程】(二)线程的创建、分离和连接

文章目录

(二)线程的创建、分离和链接

创建线程:示例

线程(Thread)是并发执行的基本单位。在C++中,std::thread用于创建和管理线程。当你想在线程中执行某个有参数或无参数的函数时,你可以将该函数传递给std::thread创建的线程对象,以下是一些示例。

示例1:传递无参数函数

cpp 复制代码
#include <iostream>
#include <thread>

void print_hello() {
    std::cout << "Hello from thread!\n";
}

int main() {
	// 创建一个 std::thread 类型的对象 t,并传递 print_hello作为t构造函数的参数。
    std::thread t(print_hello);
    t.join(); // 等待线程结束,下一节介绍其作用
    return 0;
}

示例2:传递带参数函数(拷贝)

cpp 复制代码
#include <iostream>
#include <thread>

void print_number(int num) {
    std::cout << "Number: " << num << '\n';
}

int main() {
    int value = 42;
    std::thread t(print_number, value); // 创建线程,并传入参数(value 被拷贝给线程  )
    t.join(); // 等待线程结束
    return 0;
}

示例3:传递带参数函数(使用引用或指针)

如果你希望在线程中修改传入的参数值,可以用std::ref来包装参数,以便在创建线程时传递其引用。

cpp 复制代码
#include <iostream>
#include <thread>

void modify_number(int& num) {
    num *= 2;
    std::cout << "Modified number: " << num << '\n';
}

int main() {
    int value = 42;
    std::thread t(modify_number, std::ref(value)); // 创建线程,并传入参数的引用
    t.join(); // 等待线程结束
    std::cout << "Value in main: " << value << '\n'; // 验证值已被修改
    return 0;
}
Modified number: 84
Value in main: 84

示例4:传递多个参数

你可以传递多个参数给线程函数。

cpp 复制代码
#include <iostream>
#include <thread>

void print_info(std::string name, int age) {
    std::cout << "Name: " << name << ", Age: " << age << '\n';
}

int main() {
    std::string name = "Alice";
    int age = 30;
    std::thread t(print_info, name, age); // 创建线程,并传入多个参数
    t.join(); // 等待线程结束
    return 0;
}

示例5:传递类的成员函数和实例

你还可以传递类的成员函数和类的实例给线程。

cpp 复制代码
#include <iostream>
#include <thread>

class Person {
public:
    void say_hello(const std::string& greeting) {
        std::cout << greeting << " from " << name << '\n';
    }
    std::string name = "Bob";
};

int main() {
    Person person;
    // 当线程 t 开始执行时,它会调用 person 对象的 say_hello 函数,并以 "Hello" 作为参数。
    std::thread t(&Person::say_hello, &person, "Hello"); // 创建线程,并传入成员函数和对象指针
    t.join(); // 等待线程结束
    return 0;
}

线程的分离(detach)和连接(join)。

在C++中,线程的分离(detach)和连接(join)是用于管理线程生命周期的两种主要方式。当创建一个线程时,你可以选择让它独立运行(即分离),或者等待它完成执行(即连接)。

分离(detach)

当你调用std::thread::detach()方法时,你告诉线程库你不再关心这个线程的结束时间,并且你不需要获取它的返回值。线程将在后台独立运行,直到其函数返回,结束。

示例:

cpp 复制代码
#include <iostream>  
#include <thread>  
#include <chrono>  
#include <ctime>  
#pragma warning(disable: 4996)
void thread_task() {  
	// 阻塞当前线程的执行,直到指定的时间间隔(2s)过去 
    std::this_thread::sleep_for(std::chrono::seconds(2));  
    auto now = std::chrono::system_clock::now();  
    std::time_t now_c = std::chrono::system_clock::to_time_t(now);  
    std::cout << "Hello from detached thread at " << std::ctime(&now_c) << std::endl;  
}  
  
int main() {  
    auto start_time = std::chrono::system_clock::now();  
    std::time_t start_time_c = std::chrono::system_clock::to_time_t(start_time);  
    std::cout << "Main thread starts at " << std::ctime(&start_time_c) << std::endl;  

    std::thread t(thread_task); // 创建线程  
    t.detach(); // 分离线程  
  
    // 主线程将不会等待t的结束,而是继续执行  
    std::cout << "Main thread continues execution without waiting for the detached thread.\n";  
  
    // 让主线程休眠3s,以便观察分离线程的输出  
    std::this_thread::sleep_for(std::chrono::seconds(3));  
  
    auto end_time = std::chrono::system_clock::now();  
    std::time_t end_time_c = std::chrono::system_clock::to_time_t(end_time);  
    std::cout << "Main thread ends at " << std::ctime(&end_time_c) << std::endl;  
  
    return 0;  
}

在这个例子中,t线程将开始执行thread_task函数,并在调用t.detach()后立即返回主线程。主线程将继续执行,而不需要等待t线程的完成。

Main thread starts at Fri May  3 23:02:06 2024

Main thread continues execution without waiting for the detached thread.
Hello from detached thread at Fri May  3 23:02:08 2024

Main thread ends at Fri May  3 23:02:09 2024

开始和结束相差3秒。

连接(join)

当你调用std::thread::join()方法时,你告诉线程库你想要等待这个线程完成执行后再继续下去。调用join()的线程将被阻塞,直到被连接的线程执行完毕。

示例:

cpp 复制代码
#include <iostream>  
#include <thread>  
#include <chrono>  
#include <ctime>  
#pragma warning(disable: 4996)
void thread_task() {  
	// // 休眠2s
    std::this_thread::sleep_for(std::chrono::seconds(2));  
    auto now = std::chrono::system_clock::now();  
    std::time_t now_c = std::chrono::system_clock::to_time_t(now);  
    std::cout << "Hello from joined thread at " << std::ctime(&now_c) << std::endl;  
}  
  
int main() {  
    auto start_time = std::chrono::system_clock::now();  
    std::time_t start_time_c = std::chrono::system_clock::to_time_t(start_time);  
    std::cout << "Main thread starts at " << std::ctime(&start_time_c) << std::endl;  
  
    std::thread t(thread_task); // 创建线程  
  
    // 主线程将在这里阻塞,等待t的完成  
    t.join();  
  
    std::cout << "Main thread continues execution after the thread is joined.\n";  
    std::this_thread::sleep_for(std::chrono::seconds(3));  
    auto end_time = std::chrono::system_clock::now();  
    std::time_t end_time_c = std::chrono::system_clock::to_time_t(end_time);  
    std::cout << "Main thread ends at " << std::ctime(&end_time_c) << std::endl;  
  
    return 0;  
}

在这个例子中,t线程将开始执行thread_task函数,而主线程在调用t.join()时将阻塞,等待t线程完成。当t线程完成后,主线程将继续执行。

cpp 复制代码
Main thread starts at Fri May  3 23:11:45 2024

Hello from joined thread at Fri May  3 23:11:47 2024

Main thread continues execution after the thread is joined.
Main thread ends at Fri May  3 23:11:50 2024

开始和结束相差5秒。

相关推荐
娅娅梨29 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
兵哥工控33 分钟前
MFC工控项目实例二十九主对话框调用子对话框设定参数值
c++·mfc
我爱工作&工作love我41 分钟前
1435:【例题3】曲线 一本通 代替三分
c++·算法
娃娃丢没有坏心思1 小时前
C++20 概念与约束(2)—— 初识概念与约束
c语言·c++·现代c++
lexusv8ls600h1 小时前
探索 C++20:C++ 的新纪元
c++·c++20
lexusv8ls600h1 小时前
C++20 中最优雅的那个小特性 - Ranges
c++·c++20
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
依旧阳光的老码农2 小时前
标准C++ 字符串
开发语言·c++
白-胖-子2 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-成绩排序
c++·算法·蓝桥杯·真题·蓝桥等考