C++线程库

1. 基本概念

1.1 线程(Thread)

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程可以并发多个线程,每条线程并行执行不同的任务。

1.2 并发与并行

  • 并发(Concurrency):指多个任务在同一时间段内交替执行。
  • 并行(Parallelism):指多个任务在同一时刻同时执行,通常需要多核处理器。

1.3 同步与互斥

  • 同步(Synchronization):协调多个线程的执行顺序,确保共享资源的安全访问。
  • 互斥(Mutex):确保同一时间只有一个线程可以访问共享资源。

2. 常用函数及其用法

-thread函数

2.1构造函数

用于创建一个新线程,并指定要执行的函数及其参数。

cpp 复制代码
#include <iostream>
#include <thread>
using namespace std;
void func(int x, string str) {
    cout << "Thread running with x = " << x << " and str = " << str << endl;
}

int main() {
    int a = 5;
    string s = "Hello";
    thread t(func, a, s); // 创建线程,执行func函数
    t.join(); // 等待线程完成,主线程会阻塞直到子线程结束。
    return 0;
}

detach() 函数

将线程分离,使其在后台运行,主线程不再等待子线程。

cpp 复制代码
t.detach();//一旦线程被分离,就无法再与主线程同步

lock() 和unlock()

锁定互斥量,如果互斥量已被锁定,则阻塞直到解锁。

cpp 复制代码
std::mutex mtx;
mtx.lock();
// 临界区
mtx.unlock();//解锁互斥量。

lock_guard用法

自动管理互斥量的生命周期,在构造时锁定互斥量,在析构时解锁。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex mtx;

void printThread(int id) {
    lock_guard<mutex> lock(mtx); // 自动锁定
    cout << "Thread " << id << " is running." << endl;
    // 自动解锁
}

int main() {
    thread t1(printThread, 1);
    thread t2(printThread, 2);
    
    t1.join();
    t2.join();
    
    return 0;
}

unique_lock用法

提供更灵活的锁管理,可以手动锁定和解锁。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex mtx;

void func() {
    unique_lock<mutex> lock(mtx);
    // 执行操作
    lock.unlock(); // 手动解锁
    // 执行其他操作
    lock.lock(); // 重新锁定
    // 继续执行
}

int main() {
    thread t(func);
    t.join();
    return 0;
}

wait() 用法

使线程等待,直到被通知。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex mtx;
condition_variable cv;
bool ready = false;

void worker() {
    unique_lock<mutex> lock(mtx);
    cv.wait(lock, []{ return ready; }); // 等待通知
    cout << "Worker thread is running." << endl;
}

int main() {
    thread t(worker);
    
    {
        lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one(); // 唤醒一个等待的线程。同理也有notify_all唤醒所有等待的线程
    
    t.join();
    
    return 0;
}

atomic

提供原子操作,确保对变量的操作是原子的,避免数据竞争。

cpp 复制代码
#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
atomic<int> counter(0);

void increment(int n) {
    for(int i = 0; i < n; ++i) {
        counter++;
    }
}

int main() {
    thread t1(increment, 1000);
    thread t2(increment, 1000);
    
    t1.join();
    t2.join();
    
    cout << "Counter value: " << counter << endl;
    
    return 0;
}

3. 注意事项

3.1 避免数据竞争

确保对共享资源的访问是互斥的,使用互斥量或原子操作来防止数据竞争。

3.2 死锁预防

避免多个线程互相等待对方释放锁的情况。使用锁管理类如std::lock_guardstd::unique_lock可以帮助管理锁的生命周期。

3.3 线程安全

设计线程安全的类和方法,确保在多线程环境下正确处理共享资源。

3.4 性能考虑

过多的线程切换会带来性能开销,合理配置线程数量,避免过度创建线程。

3.5 异常处理

在线程函数中捕获并处理异常,避免未捕获的异常导致程序终止。

相关推荐
骑着蜗牛撵大象32712 小时前
告别内存泄漏:LLMManager架构设计与智能指针在AI SDK中的智慧选型
c++·ai·架构
quantdash_cc12 小时前
量化策略为什么需要实时行情数据?从信号产生到交易决策的时间差说起
开发语言·python·数据分析·量化交易·股票数据·quantdash
汉克老师12 小时前
CSP-J 2026 初赛试题解析(第二部分:阅读程序题(第一题))精讲
c++·csp-j·小学生·学c++编程
syagain_zsx13 小时前
算法基础篇 · 04 前缀和(C++ 题解)
c++·算法·前缀和
汉克老师14 小时前
CSP-J 2026 初赛试题解析(第三部分:完善程序题(第一题))精讲
c++·csp-j·小学生·学c++编程
逆向编程14 小时前
QGIS地图投影(CRS坐标参照系)设置
开发语言
free-elcmacom14 小时前
发际线警告!手撕《C陷阱与缺陷》终极 BOSS:signal 函数与 typedef 魔法
c语言·开发语言·visual studio code·visual studio
程序员阿鹏14 小时前
简单介绍一下软引用
java·开发语言·jvm·数据结构·后端
haluhalu.14 小时前
初识 Protobuf:微服务跨语言通信的一份契约
java·c语言·开发语言·c++·python
longxuan0115 小时前
倍增算法详解
c++·st表·倍增算法