当前位置: 首页 > news >正文

10-C++线程相关

1. 核心库:<thread>

将可调用对象(函数、函数指针、Lambda 表达式、函数对象)传递给 std::thread 构造函数来创建线程创建即启动,一旦 std::thread 对象被构造,线程立即开始执行。主线程(主线程是相对的)调用某一线程上的join() 函数,来阻塞主线程,直到该线程线程执行完毕变为非活动无连接状态。 detach()函数将线程变为无连接状态,可将线程变为后台线程(“守护线程”)。分离后,将无法再控制该线程。必须在你销毁 std::thread 对象之前调用 join()detach(),否则 std::terminate 会被调用,程序异常终止。

2. 互斥与锁:<mutex>

用于保护共享数据,防止数据竞争。互斥量类型 有最基本的互斥量std::mutex; 带超时功能的互斥量 std::timed_mutex ;允许同一线程多次加锁的可重入互斥量 std::recursive_mutex; 读写锁 std::shared_mutex

std::vector<std::thread> workers;
workers.emplace_back(worker);// 等价于 workers.push_back(std::thread(worker));
读取线程写入线程2写入线程1shared_mutexlock_shared() 获取共享锁lock() 获取互斥锁共享锁资源占用 阻塞线程unlock_shared() 释放共享锁lock() 获取互斥锁获取互斥锁,资源锁定lock_shared() 获取共享锁互斥资源占用,阻塞线程读取线程写入线程2写入线程1shared_mutex
手动实现RAII管理锁
#include <mutex>
#include <iostream>
class MutexGuard {
private:std::mutex& mutex_;
public: // explicit是一个关键字,用于修饰类的构造函数,防止编译器进行隐式类型转换。explicit MutexGuard(std::mutex& mtx) : mutex_(mtx) {mutex_.lock();  // 构造函数获取资源(锁定mutex)std::cout << "Mutex locked" << std::endl;}~MutexGuard() {mutex_.unlock(); // 析构函数释放资源(解锁mutex)std::cout << "Mutex unlocked" << std::endl;}// 禁止拷贝构造和赋值操作MutexGuard(const MutexGuard&) = delete;MutexGuard& operator=(const MutexGuard&) = delete;
};
static std::mutex mux;
void Test() {MutexGuard lock(mux);// 业务代码// 函数执行完,执行lock的析构函数释放mutex	
}

std::lock_guard 使用 RAII 管理锁的生命周期,在函数结束或异常时自动释放锁,从而避免死锁或忘记解锁的问题。 std::lock_guard<std::mutex> 变量名(std::mutes对象);

3. 条件变量:<condition_variable>

用于线程间的同步,允许线程阻塞并等待某个条件成立。 std::condition_variable:必须与 std::unique_lock<std::mutex> 配合使用。

  • 核心操作
    • wait():阻塞当前线程,直到被通知。
    • notify_one():唤醒一个等待中的线程。
    • notify_all():唤醒所有等待中的线程。
  • 虚假唤醒:等待的线程可能在没有收到通知的情况下被唤醒。因此,wait 通常需要一个谓词(条件) 来循环检查。
    • cv.wait(lock, []{ return condition; }); 是防止虚假唤醒的标准写法。

示例代码(生产者-消费者模型):

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>std::queue<int> data_queue;
std::mutex queue_mutex;
std::condition_variable queue_condvar;void producer() {for (int i = 0; i < 10; ++i) {std::this_thread::sleep_for(std::chrono::milliseconds(100));{std::lock_guard<std::mutex> lock(queue_mutex);data_queue.push(i);std::cout << "Produced: " << i << std::endl;}queue_condvar.notify_one(); // 通知一个消费者}
}void consumer() {while (true) {std::unique_lock<std::mutex> lock(queue_mutex);// 等待条件成立:队列非空。lambda 表达式是防止虚假唤醒的关键。queue_condvar.wait(lock, []{ return !data_queue.empty(); });int value = data_queue.front();data_queue.pop();lock.unlock(); // 尽早释放锁std::cout << "Consumed: " << value << std::endl;if (value == 9) break; // 简单终止条件}
}int main() {std::thread prod(producer);std::thread cons(consumer);prod.join();cons.join();return 0;
}

4. 异步操作:<future><async>

提供了一种更高层次的抽象来获取异步任务(在另一个线程中执行的函数)的结果。
std::async启动一个异步任务,返回一个 std::future 对象。 (std::future:提供了一种访问异步操作结果的机制。 get():获取结果。如果异步操作尚未完成,会阻塞当前线程直到完成。get() 只能调用一次wait():等待异步操作完成,但不获取结果。)

std::future<函数返回类型> 对象名= std::async(启动策略, 函数名, 参数1, 参数2, ...);

启动策略std::launch::async 指立即在新线程中执行。 std::launch::deferred 指延迟执行,直到在 future 上调用 get()wait() 时才在当前线程执行。

  • std::promise 是 C++11 引入的一个同步原语,通常与 std::future 配合使用,用于在线程之间传递异步操作的结果。生产者线程可以通过 promise.set_value() 设置值,消费者线程通过关联的 future.get() 来获取。
#include <iostream>
#include <future>
#include <thread>
void setValue(std::promise<int> prom) {  // future 与 函数关联std::this_thread::sleep_for(std::chrono::seconds(1));prom.set_value(42);  // 设置结果值
}
int main() {std::promise<int> prom;std::future<int> fut = prom.get_future();  // 获取关联的futurestd::thread t(setValue, std::move(prom)); // future 与 函数对应的线程关联// 阻塞等待结果int result = fut.get();std::cout << "Result: " << result << std::endl;  // 输出: Result: 42t.join();return 0;
}

5. 原子操作:<atomic>

提供了一种无需使用锁就能实现线程安全访问基本数据类型的方法。

关键知识:

  • std::atomic<T>:模板类,支持 int, long, bool, 指针等类型。
  • 内存顺序std::memory_order 允许你指定原子操作的内存同步约束(如 memory_order_relaxed, memory_order_acquire, memory_order_release 等),用于性能优化,但对初学者来说较复杂,通常使用默认的强顺序(memory_order_seq_cst)即可。
  • 常用操作load(), store(), exchange(), compare_exchange_strong/weak 等。

示例代码(无锁计数器):

#include <iostream>
#include <thread>
#include <vector>
#include <atomic>std::atomic<int> atomic_counter{0}; // 原子计数器void atomic_worker() {for (int i = 0; i < 10000; ++i) {++atomic_counter; // 此操作是原子的,无需加锁}
}int main() {std::vector<std::thread> workers;for (int i = 0; i < 4; ++i) {workers.emplace_back(atomic_worker);}for (auto &t : workers) {t.join();}std::cout << "Final atomic counter value: " << atomic_counter << std::endl; // 一定是 40000return 0;
}

  • thread_local 用于解决多线程环境中需要每个线程拥有自己独立副本的变量问题(全局变量和静态变量被所有线程共享)。它提供了一种声明线程局部存储(TLS)的方式,即每个线程都有该变量的独立实例,且在线程的生命周期内存在。

  • std::chrono 是 C++ 标准库中用于处理时间和日期的库,它提供了一系列类型和函数来进行时间点、时长和时钟的操作。

  • std::this_thread 是控制当前正在执行这段代码的线程。

std::this_thread::sleep_for(std::chrono::seconds(2));
http://www.dtcms.com/a/553952.html

相关文章:

  • 泛型引起的dubbo序列化报错
  • 专门做护肤品的网站是无锡网站建设公司排名
  • Ubuntu OpenCV C++ 获取Astra Pro摄像头图像
  • 在网站上做视频培训系统多少钱东莞网站建设排名 南城
  • 备案号网站下边备案停止网站
  • Qt Creator 18 发布,新增了对开发容器的实验性支持,并带来了诸多改进
  • 模板进阶和array
  • 深度学习------U-net系列算法
  • 淘宝客网站都用什么做个人网站注册费用
  • 怎样帮拍卖网站做策划品牌网站设计有哪些建议
  • Kubernetes Service与Pod深度解析
  • Qt Creator打开项目提示no valid settings file could be found
  • ⑥ leetcode刷题汇总(二叉树)
  • 使用 Zabbix agent 2 监控PostgreSQL
  • 网站推广产品怎么做学校网站建设维护
  • Webpack loader 的执行机制
  • 前端基础之《React(6)—webpack简介-图片模块处理》
  • 西格电力绿电直连通信实战指南:5G、工业以太网、光纤核心对比与协议无缝兼容方案
  • 企业网站有哪些功能?淘宝网页版电脑版入口
  • 排序(选择排序、直接插入排序、冒泡排序、二路归并排序)
  • 少儿编程:6-16 岁孩子的思维启蒙与能力进阶之路
  • 10/31作业
  • 前端样式局部作用域:从Scoped到CSS Modules 的完整指南
  • 穆棱建设局网站seo 哪些媒体网站可以发新闻
  • 物联网卡摄像头从前端至后台的实现过程
  • 整合多中心临床试验的转录组与病理切片数据,提出面向晚期非小细胞肺癌免疫治疗疗效预测的解决方案
  • 【计算机网络】考研408计算机网络:传输介质(导向/非导向)考点梳理
  • 网站开发合同适用印花税互联网专业主要学什么
  • iFluor 594 Styramide,水溶性荧光探针
  • 零基础网站建设及维护视频课程东莞有哪些好的网站建设公司