前言

在多线程编程领域,Linux 平台的 pthread 库曾是主流选择,但平台依赖性强的短板让跨平台开发备受阻碍。C++11 标准的推出彻底改变了这一现状 —— 它首次将线程库纳入标准,提供了一套跨平台、类型安全且易用的并发编程接口,让开发者无需关注底层系统差异,就能轻松实现多线程同步。

本文将从实际开发需求出发,系统拆解 C++11 线程库的核心组件:从 thread 类的线程创建与管理,到 mutex 系列互斥锁的锁机制应用,再到 lock_guard/unique_lock 等 RAII 包装器的优雅使用,以及 condition_variable 的线程通信和 atomic 的原子操作。每个组件都搭配具体用法、注意事项与代码示例,帮助读者快速避开踩坑点,掌握从线程启动、资源竞争控制到无锁编程的全流程技巧。无论你是刚接触并发编程的新手,还是需要从 pthread 迁移到标准库的开发者,都能通过本文建立清晰的 C++11 并发编程知识体系,轻松应对实际项目中的多线程场景。

线程库简介

Linux里面是用的pthread库,但是只能在Linux上用

C++11引入了线程库,这些接口能在所有系统上都能跑

thread

include<thread>下东西有: thread这个类

创建线程:

在这里插入图片描述

2那里的参数:第一个参数是可调用对象(函数指针,仿函数,lambda表达式,包装器),其他参数是可调用对象里面的形参

用法:eg:
void func(int a, int b, mutex& m) {.....}
    std::thread t(func, 10, 20,ref(mtx));
注意:这里必须用引用方式传过去,而且要用ref搞一下:
因为mtx会先进thread的构造函数,但是mtx不能进行拷贝,就会报错


创建线程一共两种方法:
1.带参构造,直接创建可执行线程

2.先创建空线程对象,移动构造或赋值,把右值线程对象搞过去
eg:   thread t2;//创建空线程
      t2 = move(t); 

成员函数:

get_id:获取t1线程的线程id eg:t1.get_id()

join:让当前线程阻塞等待 t1 线程执行结束 eg:t1.join()

operator=

在这里插入图片描述

拷贝构造被禁用了 只能移动拷贝

#include<thread>里面还有一个this_thread的命名空间,里面有几个函数,可以用来操作当前线程

yield:让当前线程主动 “让渡 CPU 时间片”

sleep_until:让当前线程阻塞,直到指定的 “时间点” 到来才唤醒

sleep_for:让当前线程阻塞 “指定的时长”

用法eg: this_thread::sleep_for(......);

注意:sleep_untilsleep_for里面的时间要是chrono的才行

mutex

include<mutex>下有:四个类:mutex(互斥锁) recursive_mutex(递归互斥锁) timed_mutex(定时互斥锁) recursive_timed_mutex(递归定时互斥锁)

但是最常用的还是:mutex

创建互斥锁:

在这里插入图片描述

eg:mutex mtx(拷贝和移动都不行)

类里面的成员函数:

lock:尝试 “占用这把锁”,进入阻塞等待状态,直到成功拿到锁

eg:mtx.lock()

try_lock:尝试 “占用这把锁”,但不阻塞

unlock:释放锁

这个头文件下还有俩个RAII风格锁包装器:

lock_guardunique_lock

使用了这俩其中之一的话可以实现进和出作用域自用加解锁

eg:
mutex mtx;

func()
{
 lock_guard<mutex> lock(mtx);
//unique_lock<mutex> lock(mtx);
这样的话在lock之后就自动加锁,出了func就自动解锁
}

lock_guardunique_lock的区别:

unique_lock可以跟time_mutex配合使用;还支持手动解锁再加锁

这俩点lock_guard都不行

C++里面没有提供自旋锁,想要用的话要自己实现

condition_variable

include<condition_variable>里面有一个类:condition_variable

他里面有几个成员函数:

wait:阻塞当前线程,直到被唤醒;阻塞时会释放锁,被唤醒了会重新获得锁

在这里插入图片描述

用法:eg:
condition_variable cv;  cv.wait(mtx);

wait_for wait_until

notify_one:叫醒一个在wait的线程

notify_all:叫醒全部在wait的线程,谁能抢到锁就看天意了–没抢到的就继续wait,但是不需要唤醒了

waitunlock的区别:

unlock是单一的释放锁 wait是释放完,被唤醒了的话,会重新排队去获得锁

atomic

include<atomic>里面有一个模板类:atomic

在这里插入图片描述

用法:

atomic<int>x = 0;
这个类里面的接口都能保证该操作是原子性的:
eg:operator++

这个类常用来实现无锁编程

引申:一般一条汇编指令就是原子的

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐