std::thread的使用

一 概述

std::thread 是 C++11 引入的线程库,用于创建和管理多线程程序。

二 基本用法

1 创建线程

#include <iostream>

#include <thread>

// 普通函数作为线程函数

void hello() {

std::cout << "Hello from thread!" << std::endl;

}

// Lambda表达式作为线程函数

auto lambda = []() {

std::cout << "Hello from lambda thread!" << std::endl;

};

// 带参数的函数

void print_number(int num) {

std::cout << "Number: " << num << std::endl;

}

int main() {

// 创建线程

std::thread t1(hello);

std::thread t2(lambda);

std::thread t3(print_number, 42);

// 等待线程完成

t1.join();

t2.join();

t3.join();

return 0;

}

2 类成员函数作为线程函数

#include <iostream>

#include <thread>

class MyClass {

public:

void member_func(int x) {

std::cout << "Member function: " << x << std::endl;

}

static void static_func() {

std::cout << "Static member function" << std::endl;

}

};

int main() {

MyClass obj;

// 调用成员函数

std::thread t1(&MyClass::member_func, &obj, 100);

// 调用静态成员函数

std::thread t2(&MyClass::static_func);

t1.join();

t2.join();

return 0;

}

```

二 线程管理

1 join() 和 detach()

#include <iostream>

#include <thread>

#include <chrono>

void worker() {

std::this_thread::sleep_for(std::chrono::seconds(1));

std::cout << "Worker thread finished" << std::endl;

}

int main() {

std::thread t1(worker);

if (t1.joinable()) {

// join() - 等待线程结束

t1.join();

}

std::thread t2(worker);

if (t2.joinable()) {

// detach() - 分离线程(后台运行)

t2.detach();

}

// 注意:分离后不能再 join()

// t2.join(); // 错误!

// 主线程等待,确保分离的线程有机会执行

std::this_thread::sleep_for(std::chrono::seconds(2));

return 0;

}

2 获取线程ID

#include <iostream>

#include <thread>

void print_id() {

std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;

}

int main() {

std::thread t1(print_id);

std::thread t2(print_id);

std::cout << "Main thread ID: " << std::this_thread::get_id() << std::endl;

std::cout << "t1 ID: " << t1.get_id() << std::endl;

t1.join();

t2.join();

return 0;

}

三 传递参数

1 按值传递

#include <iostream>

#include <thread>

void func(int a, std::string b, double c) {

std::cout << "a=" << a << ", b=" << b << ", c=" << c << std::endl;

}

int main() {

std::thread t(func, 1, "hello", 3.14);

t.join();

return 0;

}

2 按引用传递

#include <iostream>

#include <thread>

#include <functional> // 需要 std::ref

void modify_value(int& x) {

x = 100;

}

int main() {

int value = 0;

// 使用 std::ref 传递引用

std::thread t(modify_value, std::ref(value));

t.join();

std::cout << "Value after modification: " << value << std::endl; // 输出 100

return 0;

}

3 传递指针

#include <iostream>

#include <thread>

void process_array(int* arr, int size) {

for (int i = 0; i < size; ++i) {

arr[i] *= 2;

}

}

int main() {

int arr[] = {1, 2, 3, 4, 5};

std::thread t(process_array, arr, 5);

t.join();

for (int num : arr) {

std::cout << num << " "; // 输出: 2 4 6 8 10

}

std::cout << std::endl;

return 0;

}

四 线程同步

1 使用互斥锁

#include <iostream>

#include <thread>

#include <mutex>

#include <vector>

std::mutex mtx;

int counter = 0;

void increment() {

for (int i = 0; i < 10000; ++i) {

mtx.lock(); // 上锁

++counter;

mtx.unlock(); // 解锁

}

}

int main() {

std::thread t1(increment);

std::thread t2(increment);

t1.join();

t2.join();

std::cout << "Counter value: " << counter << std::endl; // 应该是 20000

return 0;

}

2 使用 RAII 风格的锁

#include <iostream>

#include <thread>

#include <mutex>

std::mutex mtx;

int counter = 0;

void increment() {

for (int i = 0; i < 10000; ++i) {

std::lock_guard<std::mutex> lock(mtx); // 自动加锁解锁

++counter;

}

}

int main() {

std::thread t1(increment);

std::thread t2(increment);

t1.join();

t2.join();

std::cout << "Counter value: " << counter << std::endl;

return 0;

}

五 线程移动

#include <iostream>

#include <thread>

#include <vector>

void worker(int id) {

std::cout << "Worker " << id << " started" << std::endl;

}

int main() {

// 线程对象不能复制,只能移动

std::thread t(worker, 1);

// 移动语义

std::thread t2 = std::move(t);

// t 现在为空,不能再使用

// t.join(); // 错误!

if (t2.joinable()) {

t2.join();

}

// 线程向量

std::vector<std::thread> threads;

for (int i = 0; i < 5; ++i) {

// 使用 emplace_back 直接构造

threads.emplace_back(worker, i);

}

// 等待所有线程完成

for (auto& t : threads) {

if (t.joinable()) {

t.join();

}

}

return 0;

}

六 实用技巧

1 使用 packaged_task

#include <iostream>

#include <thread>

#include <future>

#include <functional>

int compute(int x, int y) {

return x * y;

}

int main() {

std::packaged_task<int(int, int)> task(compute);

std::future<int> result = task.get_future();

// 在新线程中执行任务

std::thread t(std::move(task), 6, 7);

// 获取结果

std::cout << "Result: " << result.get() << std::endl;

t.join();

return 0;

}

2 线程睡眠

#include <iostream>

#include <thread>

#include <chrono>

void slow_worker() {

std::cout << "Worker starting..." << std::endl;

// 睡眠 2 秒

std::this_thread::sleep_for(std::chrono::seconds(2));

std::cout << "Worker finished!" << std::endl;

}

int main() {

std::thread t(slow_worker);

t.join();

return 0;

}

七 注意事项

1 资源管理:确保线程在析构前被 join() 或 detach()。

2 数据竞争:使用适当的同步机制。

3 异常安全:线程函数中的异常需要处理。

4 性能考虑:避免创建过多线程。

5 平台差异:线程行为在不同操作系统上可能略有不同。

八 完整示例

#include <iostream>

#include <thread>

#include <vector>

#include <mutex>

#include <chrono>

class ThreadPool {

private:

std::vector<std::thread> workers;

std::mutex mtx;

public:

void add_worker(int id) {

workers.emplace_back([this, id]() {

{

std::lock_guard<std::mutex> lock(mtx);

std::cout << "Worker " << id << " started" << std::endl;

}

std::this_thread::sleep_for(std::chrono::milliseconds(100));

{

std::lock_guard<std::mutex> lock(mtx);

std::cout << "Worker " << id << " finished" << std::endl;

}

});

}

void wait_all() {

for (auto& t : workers) {

if (t.joinable()) {

t.join();

}

}

}

};

int main() {

ThreadPool pool;

// 创建 10 个工作线程

for (int i = 0; i < 10; ++i) {

pool.add_worker(i);

}

// 等待所有线程完成

pool.wait_all();

std::cout << "All workers finished!" << std::endl;

return 0;

}

这个示例展示了 std::thread 的主要用法。实际使用时,建议考虑使用更高级的抽象,如 C++17 的 std::jthread 或第三方线程池库。

相关推荐
在路上看风景4 小时前
19. 成员初始化列表和初始化对象
c++
zmzb01034 小时前
C++课后习题训练记录Day98
开发语言·c++
念风零壹5 小时前
C++ 内存避坑指南:如何用移动语义和智能指针解决“深拷贝”与“内存泄漏”
c++
孞㐑¥5 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法
MZ_ZXD0017 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
A星空1238 小时前
一、Linux嵌入式的I2C驱动开发
linux·c++·驱动开发·i2c
凡人叶枫8 小时前
C++中智能指针详解(Linux实战版)| 彻底解决内存泄漏,新手也能吃透
java·linux·c语言·开发语言·c++·嵌入式开发
会叫的恐龙8 小时前
C++ 核心知识点汇总(第六日)(字符串)
c++·算法·字符串
小糯米6019 小时前
C++顺序表和vector
开发语言·c++·算法
独望漫天星辰9 小时前
C++ 多态深度解析:从语法规则到底层实现(附实战验证代码)
开发语言·c++