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 或第三方线程池库。

相关推荐
Eloudy2 小时前
通过示例看 C++ 函数对象、仿函数、operator( )
开发语言·c++·算法
superman超哥2 小时前
仓颉高性能实践:内存布局优化技巧深度解析
c语言·开发语言·c++·python·仓颉
Q741_1472 小时前
Linux UDP 服务端 实战思路 C++ 套接字 源码包含客户端与服务端 游戏服务端开发基础
linux·服务器·c++·游戏·udp
游戏23人生2 小时前
c++ 语言教程——17面向对象设计模式(六)
开发语言·c++·设计模式
superman超哥2 小时前
仓颉内存管理内功:栈与堆的分配策略深度解析
c语言·开发语言·c++·python·仓颉
ALex_zry2 小时前
C++中的“虚“机制解析:虚函数、纯虚函数与虚基类
c++
加成BUFF2 小时前
C++入门讲解6:数据的共享与保护核心机制解析与实践
开发语言·c++
ht巷子3 小时前
Qt:容器类
开发语言·c++·qt
superman超哥3 小时前
仓颉协程调度机制深度解析:高并发的秘密武器
c语言·开发语言·c++·python·仓颉