C++基础 | 线程`std::thread`

news/2025/2/12 23:40:34/

什么是std::thread

std::thread是C++11中引入的一个类,用于表示和管理线程。通过std::thread,我们可以创建一个新的线程来执行指定的任务。线程是操作系统调度的基本单位,多个线程可以并发执行,从而提高程序的效率。


创建线程

基本用法

要创建一个线程,只需实例化一个std::thread对象,并传入一个可调用对象(如函数、Lambda表达式或函数对象)作为参数。

#include <iostream>
#include <thread>void hello() {std::cout << "Hello from thread!\n";
}int main() {std::thread t(hello); // 创建一个线程,执行hello函数t.join(); // 等待线程结束return 0;
}

在这个示例中,我们创建了一个线程t,它执行hello函数。join()方法用于等待线程执行完毕。


使用Lambda表达式

我们也可以使用Lambda表达式来创建线程。

#include <iostream>
#include <thread>int main() {std::thread t([]() {std::cout << "Hello from Lambda thread!\n";});t.join();return 0;
}

带参数的线程函数

线程函数可以接受参数,只需在创建线程时传递相应的参数即可。

#include <iostream>
#include <thread>void print_message(const std::string& message) {std::cout << message << '\n';
}int main() {std::thread t(print_message, "Hello from thread with arguments!");t.join();return 0;
}

线程的管理

join()detach()

  • join():等待线程执行完毕。调用join()后,主线程会阻塞,直到子线程完成。
  • detach():将线程与std::thread对象分离,线程在后台独立运行。分离后的线程不能再被join()
#include <iostream>
#include <thread>
#include <chrono>void task() {std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Task completed!\n";
}int main() {std::thread t(task);t.detach(); // 分离线程std::cout << "Main thread continues...\n";std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待子线程完成return 0;
}

线程的移动语义

std::thread支持移动语义,可以将一个线程的所有权从一个std::thread对象转移到另一个。

#include <iostream>
#include <thread>void task() {std::cout << "Task executed!\n";
}int main() {std::thread t1(task);std::thread t2 = std::move(t1); // 将t1的所有权转移给t2t2.join();return 0;
}

线程同步

多线程编程中,线程之间的共享资源可能会导致数据竞争问题。为了解决这个问题,C++提供了多种同步机制,如互斥锁(std::mutex)和条件变量(std::condition_variable)。


使用std::mutex

std::mutex用于保护共享资源,确保同一时间只有一个线程可以访问该资源。

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>std::mutex mtx;
int shared_data = 0;void increment() {for (int i = 0; i < 10000; ++i) {std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁++shared_data;}
}int main() {std::vector<std::thread> threads;for (int i = 0; i < 10; ++i) {threads.emplace_back(increment);}for (auto& t : threads) {t.join();}std::cout << "Final value of shared_data: " << shared_data << '\n'; // 输出:100000return 0;
}

使用std::condition_variable

std::condition_variable用于线程间的通信,允许线程等待某些条件成立。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
bool ready = false;void print_id(int id) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []() { return ready; }); // 等待条件成立std::cout << "Thread " << id << " is running!\n";
}int main() {std::thread threads[10];for (int i = 0; i < 10; ++i) {threads[i] = std::thread(print_id, i);}std::this_thread::sleep_for(std::chrono::seconds(1));{std::lock_guard<std::mutex> lock(mtx);ready = true; // 设置条件为true}cv.notify_all(); // 通知所有等待的线程for (auto& t : threads) {t.join();}return 0;
}

线程池的实现

虽然C++标准库没有直接提供线程池,但我们可以使用std::thread和其他工具(如std::queuestd::function)来实现一个简单的线程池。

#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>class ThreadPool {
public:ThreadPool(size_t num_threads) {for (size_t i = 0; i < num_threads; ++i) {workers.emplace_back([this] {while (true) {std::function<void()> task;{std::unique_lock<std::mutex> lock(this->queue_mutex);this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });if (this->stop && this->tasks.empty()) {return;}task = std::move(this->tasks.front());this->tasks.pop();}task();}});}}template <class F>void enqueue(F&& f) {{std::unique_lock<std::mutex> lock(queue_mutex);tasks.emplace(std::forward<F>(f));}condition.notify_one();}~ThreadPool() {{std::unique_lock<std::mutex> lock(queue_mutex);stop = true;}condition.notify_all();for (std::thread& worker : workers) {worker.join();}}private:std::vector<std::thread> workers;std::queue<std::function<void()>> tasks;std::mutex queue_mutex;std::condition_variable condition;bool stop = false;
};int main() {ThreadPool pool(4);for (int i = 0; i < 8; ++i) {pool.enqueue([i] {std::cout << "Task " << i << " is running on thread " << std::this_thread::get_id() << '\n';std::this_thread::sleep_for(std::chrono::seconds(1));});}return 0;
}

http://www.ppmy.cn/news/1571553.html

相关文章

C# OpenCV机器视觉:SoftNMS非极大值抑制

嘿&#xff0c;你知道吗&#xff1f;阿强最近可忙啦&#xff01;他正在处理一个超级棘手的问题呢&#xff0c;就好像在一个混乱的战场里&#xff0c;到处都是乱糟糟的候选框&#xff0c;这些候选框就像一群调皮的小精灵&#xff0c;有的重叠在一起&#xff0c;让阿强头疼不已。…

单片机之基本元器件的工作原理

一、二极管 二极管的工作原理 二极管是一种由P型半导体和N型半导体结合形成的PN结器件&#xff0c;具有单向导电性。 1. PN结形成 P型半导体&#xff1a;掺入三价元素&#xff0c;形成空穴作为多数载流子。N型半导体&#xff1a;掺入五价元素&#xff0c;形成自由电子作为多…

支持向量机相关文献

根据最新的研究动态和文献综述&#xff0c;当前支持向量机&#xff08;SVM&#xff09;的研究方向和内容主要集中在以下几个方面&#xff1a; 1. 提高训练效率 并行计算与分布式计算&#xff1a;随着数据规模的增加&#xff0c;SVM的训练时间往往较长&#xff0c;难以满足实时…

[转]Java面试近一个月的面试总结

本文是在学习中的总结&#xff0c;欢迎转载但请注明出处&#xff1a;http://blog.csdn.net/pistolove/article/details/46753275 前言 打算换个工作&#xff0c;近一个月面试了不少的公司&#xff0c;下面将一些面试经验和思考分享给大家。另外校招也快要开始了&#xff0c;为…

《从入门到精通:蓝桥杯编程大赛知识点全攻略》(十一)-回文日期、移动距离、日期问题

前言 在这篇博客中&#xff0c;我们将通过模拟的方法来解决三道经典的算法题&#xff1a;回文日期、移动距离和日期问题。这些题目不仅考察了我们的基础编程能力&#xff0c;还挑战了我们对日期处理和数学推理的理解。通过模拟算法&#xff0c;我们能够深入探索每个问题的核心…

SpringBoot集成Milvus,实现数据增删改查

Milvus是一款开源向量数据库&#xff0c;主要用于在大模型领域做向量查询的相关操作。milvus支持的语言比较多&#xff0c;支持python, Java, Go,node等开发语言。本文主要介绍如何使用Java语言&#xff0c;采用springboot框架集成和调用Milvus数据库。 本文示例使用的milvus版…

ASP.NET Core DDD

目录 什么是微服务 单体结构项目 微服务架构项目 微服务架构误区 什么是DDD DDD领域与领域模型 领域&#xff08;Domain&#xff09; 领域模型&#xff08;Domain Model&#xff09; 事务脚本 事务脚本的问题 通用语言与界限上下文 通用语言 界限上下文 实体与值…

龙迅LT8711UXD 高性能2PORT TYPE-CDPEDP转HDMi 2.0加PD 3.0,内置MCU

龙迅LT8711UXD描述&#xff1a; LT8711UXD是一款高性能的双车道TypeC/DP1.4到HDMI2.0转换器&#xff0c;设计用于将USB Type-C源或DP1.4源连接到HDMI2.0接收器。LT8711UXD集成了一个DP1.4兼容的接收机&#xff0c;和一个HDMI2.0兼容的发射机。此外&#xff0c;还包括两个CC控制…