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

多线程开发

基本线程操作

1. 创建线程

#include <iostream>
#include <thread>void threadFunc() {std::cout << "子线程正在执行..." << std::endl;
}int main() {std::thread t(threadFunc);  // 创建并启动线程std::cout << "主线程等待子线程..." << std::endl;t.join();  // 主线程阻塞,等待 t 执行完毕std::cout << "子线程已结束,主线程继续。" << std::endl;return 0;
}
  • t.join() 会阻塞当前线程(通常是主线程或调用 join 的线程),直到线程 t 执行完毕。

  • 调用 join() 后,主线程会暂停,等待子线程 t 完成任务后才会继续执行。

关键点

  • 同步线程:确保主线程等待子线程完成后再继续或退出。

  • 资源清理:join() 会释放线程 t 的系统资源(如线程 ID、栈内存等)。

  • 必须调用:如果线程对象 t 是 joinable 的(即已关联线程且未 join 或 detach),在销毁前必须调用 join() 或 detach(),否则程序会调用 std::terminate() 终止。

注意事项

  • 如果忘记调用 join() 或 detach(),程序会异常终止。

  • 不能对同一个线程多次调用 join()(会导致 std::system_error)。

  • 可以通过 t.joinable() 检查线程是否需要 join。

对比 detach()

  • t.detach():分离线程,让线程独立运行,主线程不再等待(失去对线程的控制权)。

  • t.join():等待线程结束,保持控制权。

2. 带参数的线程函数

void printMessage(const std::string& message) {std::cout << message << std::endl;
}int main() {std::thread t(printMessage, "Hello from thread with args!");t.join();return 0;
}

3. 分离线程

std::thread t(backgroundTask);
t.detach();  // 线程将独立运行,主线程不再等待

线程同步

1. 互斥锁(Mutex)
作用:防止多个线程同时访问共享资源,确保同一时间只有一个线程可以访问临界区(Critical Section)。
C++ 标准库支持:std::mutex, std::lock_guard, std::unique_lock

#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;  // 全局互斥锁
int shared_data = 0;void increment() {std::lock_guard<std::mutex> lock(mtx);  // 自动加锁,离开作用域解锁shared_data++;  // 临界区
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Shared data: " << shared_data << std::endl;  // 输出 2return 0;
}
  • std::lock_guard 是 RAII 风格锁,自动管理锁的生命周期。

  • std::unique_lock 更灵活,支持手动 lock() 和 unlock()。

2. 条件变量(Condition Variable)
作用:让线程等待某个条件成立,避免忙等待(Busy Waiting),通常与互斥锁配合使用。
C++ 标准库支持:std::condition_variable
成员函数:

  • wait(lock, predicate) :阻塞当前线程,直到被唤醒且 predicate 返回 true(防止虚假唤醒)。
  • notify_one() :随机唤醒一个等待的线程。
  • notify_all() :唤醒所有等待的线程。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
bool ready = false;void worker() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return ready; });  // 等待 ready == truestd::cout << "Worker thread is processing..." << std::endl;
}int main() {std::thread t(worker);{ std::lock_guard<std::mutex> lock(mtx);ready = true;  // 修改条件}cv.notify_one();  // 通知等待的线程t.join();return 0;
}
  • cv.wait() 会释放锁并进入等待状态,直到被 notify_one() 或 notify_all() 唤醒。

  • 防止虚假唤醒(Spurious Wakeup),通常搭配 while 或 predicate 检查条件。

3. 原子操作(Atomic Operations)
作用:对基本数据类型(如 int, bool)提供无锁(Lock-Free)的线程安全操作。
C++ 标准库支持:std::atomic<T>

#include <iostream>
#include <thread>
#include <atomic>std::atomic<int> counter(0);void increment() {counter++;  // 原子操作,无需锁
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Counter: " << counter << std::endl;  // 输出 2return 0;
}

4. 读写锁(Read-Write Lock)
作用:允许多个线程同时读,但写操作独占资源(适用于读多写少的场景)。
C++ 标准库支持:std::shared_mutex(C++17)

#include <iostream>
#include <thread>
#include <shared_mutex>std::shared_mutex rw_mutex;
int data = 0;void reader() {std::shared_lock<std::shared_mutex> lock(rw_mutex);  // 共享读锁std::cout << "Read data: " << data << std::endl;
}void writer() {std::unique_lock<std::shared_mutex> lock(rw_mutex);  // 独占写锁data++;
}int main() {std::thread readers[3] = {std::thread(reader), std::thread(reader), std::thread(reader)};std::thread writer_thread(writer);for (auto& t : readers) t.join();writer_thread.join();return 0;
}
  • 读锁(shared_lock)允许多线程并发读。

  • 写锁(unique_lock)独占资源,阻塞所有读写操作。

5. 信号量(Semaphore)
作用:控制同时访问资源的线程数量(C++20 引入 std::counting_semaphore)。

#include <iostream>
#include <thread>
#include <semaphore>std::counting_semaphore<5> sem(5);  // 允许最多 5 个线程同时访问void worker(int id) {sem.acquire();  // 获取信号量std::cout << "Thread " << id << " is working..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));sem.release();  // 释放信号量
}int main() {std::thread threads[10];for (int i = 0; i < 10; i++) {threads[i] = std::thread(worker, i);}for (auto& t : threads) t.join();return 0;
}
  • 适用于限流场景(如线程池、数据库连接池)。

6. 屏障(Barrier)
作用:让多个线程在某个点同步,等待所有线程到达后再继续(C++20 引入 std::barrier)。

#include <iostream>
#include <thread>
#include <barrier>std::barrier sync_point(3);  // 等待 3 个线程void worker(int id) {std::cout << "Thread " << id << " started" << std::endl;sync_point.arrive_and_wait();  // 等待其他线程std::cout << "Thread " << id << " continued" << std::endl;
}int main() {std::thread t1(worker, 1);std::thread t2(worker, 2);std::thread t3(worker, 3);t1.join(); t2.join(); t3.join();return 0;
}
  • 适用于分阶段并行计算(如 MapReduce)。

总结

同步方式 适用场景 C++ 标准支持
互斥锁(Mutex) 保护共享数据,避免竞态条件 C++11
条件变量 线程间事件通知(生产者-消费者模型) C++11
原子操作 简单变量的无锁操作 C++11
读写锁 读多写少的场景 C++17
信号量 限流(如线程池) C++20
屏障 多线程分阶段同步 C++20
http://www.sczhlp.com/news/7277/

相关文章:

  • Linux部署RocketMQ Dashboard,以及开启ACL权限控制
  • 基于DWT、矢量量化和自动分片的遥感图像半脆弱水印技术
  • keil MDK中debug时程序无法自行运行的问题
  • 前端-html+CSS基础到高级(六)html列表标签和表格标签 - 努力-
  • 小白编码知识乱码应对方案
  • html+CSS基础到高级(七)input表单标签 - 努力-
  • 国产化Excel处理组件Spire.XLS教程:使用 C# 将 DataTable 导出为 Excel 文件
  • 压缩感知中的OMP算法的实现
  • Helm 常用命令
  • GPU半虚拟化(GPU-PV,Easy-GPU-PV) 不稳定的问题
  • mac mini m4 用putty连接中文乱码 echo export LANG=zh_CN.UTF-8 ~/.zshrc source ~/.zshrc
  • .NET PDF处理组件IronPDF:如何通过 AI 简化开发人员处理 PDF的方式
  • 记录一次VMware虚拟机启动提示:此虚拟机似乎正在使用中,无法取得所有权的解决办法
  • Gitblit的基本操作和技巧
  • 等保和FB的系统定级,测评流程
  • 数据结构
  • 添加Helm源
  • 产品管理软件Top10,2025年助你高效管理产品全生命周期!
  • ARM架构离线Python环境部署
  • 前端-上传文件/图片至oss服务
  • 第四届电子信息技术国际学术会议(EIT 2025)
  • Java面向对象——7.接口
  • 企业需要什么样的低代码平台?
  • .NET 10 新增功能系列文章(5)——C# 14 中的新增功能
  • 手撸一个Vue(看不懂可以举报)
  • 良乡地图
  • 宏基因组Trim galore质控+MEGAHIT组装
  • Sealing Enclave相关知识点, 来自kimi
  • 如何查看别人的个人主页
  • 第十届现代管理、教育与社会科学国际学术会议(MMET 2025)