
1. 基本多线程编程1.1 创建线程123456789101112#include iostream#include threadvoidthread_function() {std::cout Hello from thread!\n;}intmain() {std::threadt(thread_function);// 创建并启动线程t.join();// 等待线程结束return0;}1.2 带参数的线程函数123456789101112#include thread#include iostreamvoidprint_num(intnum) {std::cout Number: num \n;}intmain() {std::threadt(print_num, 42);t.join();return0;}1.3 join() 和 detach()123456789101112std::threadt(threadFunction);// join() - 等待线程完成t.join();// detach() - 分离线程线程独立运行// t.detach();// 检查线程是否可joinableif(t.joinable()) {t.join();}1.4 获取当前线程信息12345678910111213#include thread#include iostreamintmain() {std::cout Main thread ID: std::this_thread::get_id() std::endl;std::threadt([](){std::cout Worker thread ID: std::this_thread::get_id() std::endl;});t.join();return0;}1.5 线程休眠123456789#include chrono#include threadintmain() {std::cout Sleeping for 2 seconds... std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));std::cout Awake! std::endl;return0;}2. mutex (互斥锁)12345678910111213141516171819202122232425#include thread#include mutex#include iostreamstd::mutex mtx;// 全局互斥锁intshared_data 0;voidincrement() {for(inti 0; i 100000; i) {mtx.lock();// 上锁shared_data;mtx.unlock();// 解锁}}intmain() {std::threadt1(increment);std::threadt2(increment);t1.join();t2.join();std::cout Final value: shared_data \n;return0;}2.1 lock_guard (自动管理锁)lock_guard在构造时自动上锁在析构时自动解锁防止忘记解锁123456voidincrement_safe() {for(inti 0; i 100000; i) {std::lock_guardstd::mutex lock(mtx);// 自动上锁shared_data;}// 自动解锁}2.2 unique_lockunique_lock比lock_guard更灵活可以手动上锁和解锁。12345678910voidincrement_flexible() {for(inti 0; i 100000; i) {std::unique_lockstd::mutex lock(mtx);shared_data;lock.unlock();// 可以手动解锁// 做一些不需要锁的操作lock.lock();// 再手动上锁shared_data;}}2.3 尝试锁try_lock()12345678910voidtryLockExample() {std::unique_lockstd::mutex lock(mtx, std::try_to_lock);if(lock.owns_lock()) {// 成功获取锁std::cout Got the lock!\n;}else{// 未能获取锁std::cout Couldnt get the lock, doing something else...\n;}}2.4 递归互斥锁std::recursive_mutex1234567891011121314151617#include mutexstd::recursive_mutex rec_mtx;voidrecursiveFunction(intcount) {std::lock_guardstd::recursive_mutex lock(rec_mtx);if(count 0) {std::cout Count: count \n;recursiveFunction(count - 1);}}intmain() {std::threadt(recursiveFunction, 3);t.join();return0;}2.5 定时互斥锁std::timed_mutex1234567891011121314151617#include mutex#include chronostd::timed_mutex timed_mtx;voidtimedLockExample() {auto timeout std::chrono::milliseconds(100);if(timed_mtx.try_lock_for(timeout)) {// 在100ms内成功获取锁std::this_thread::sleep_for(std::chrono::milliseconds(50));timed_mtx.unlock();}else{// 超时未能获取锁std::cout Could not get the lock within 100ms\n;}}2.6std::adopt_lock与std::defer_lock特性std::adopt_lockstd::defer_lock用途表示锁已被当前线程获得表示不立即获取锁加锁时机不尝试加锁假设已锁定稍后手动加锁典型使用场景与 std::lock 配合使用延迟加锁或条件加锁可用性适用于 lock_guard 和 unique_lock仅适用于 unique_lockadopt_lock表示当前线程已经获得了互斥锁的所有权不需要再尝试加锁12345678910111213#include mutexstd::mutex mtx;voidfunction() {mtx.lock();// 手动加锁// 使用 adopt_lock 告诉 lock_guard 我们已经拥有锁std::lock_guardstd::mutex lock(mtx, std::adopt_lock);// 临界区代码...// 离开作用域时自动解锁}3. 条件变量 (condition_variable)用于线程间的同步允许线程等待特定条件成立。123456789101112131415161718192021222324252627#include thread#include mutex#include condition_variable#include iostreamstd::mutex mtx;std::condition_variable cv;boolready false;voidworker() {std::unique_lockstd::mutex lock(mtx);cv.wait(lock, []{returnready; });// 等待ready变为truestd::cout Worker is processing data\n;}intmain() {std::threadt(worker);{std::lock_guardstd::mutex lock(mtx);ready true;}cv.notify_one();// 通知等待的线程t.join();return0;}3.1wait12std::unique_lockstd::mutex lock(mtx);cv.wait(lock);// 无条件等待可能虚假唤醒带谓词的wait()1234cv.wait(lock, []{returnready; });// 等价于:// while (!ready) {// cv.wait(lock);// }wait_for()- 带超时等待123456usingnamespacestd::chrono_literals;if(cv.wait_for(lock, 100ms, []{returnready; })) {// 条件在超时前满足}else{// 超时}wait_until()- 等待到指定时间点123456auto timeout std::chrono::steady_clock::now() 100ms;if(cv.wait_until(lock, timeout, []{returnready; })) {// 条件在时间点前满足}else{// 超时}3.2notifynotify_one()- 通知一个等待线程12345{std::lock_guardstd::mutex lock(mtx);ready true;}cv.notify_one();// 只唤醒一个等待线程notify_all()- 通知所有等待线程12345{std::lock_guardstd::mutex lock(mtx);ready true;}cv.notify_all();// 唤醒所有等待线程3.3 生产消费者模式示例123456789101112131415161718192021222324252627282930313233343536373839404142434445464748#include queue#include chronostd::mutex mtx;std::condition_variable cv;std::queueint data_queue;constintMAX_SIZE 10;voidproducer() {for(inti 0; i 20; i) {std::unique_lockstd::mutex lock(mtx);cv.wait(lock, []{returndata_queue.size() MAX_SIZE; });data_queue.push(i);std::cout Produced: i std::endl;lock.unlock();cv.notify_all();std::this_thread::sleep_for(std::chrono::milliseconds(100));}}voidconsumer() {while(true) {std::unique_lockstd::mutex lock(mtx);cv.wait(lock, []{return!data_queue.empty(); });intdata data_queue.front();data_queue.pop();std::cout Consumed: data std::endl;lock.unlock();cv.notify_all();if(data 19)break;// 结束条件}}intmain() {std::threadp(producer);std::threadc(consumer);p.join();c.join();return0;}4. 原子操作 (atomic)对于简单的数据类型可以使用原子操作避免锁的开销。12345678910111213141516171819202122#include atomic#include thread#include iostreamstd::atomicint counter(0);voidincrement_atomic() {for(inti 0; i 100000; i) {counter;// 原子操作无需锁}}intmain() {std::threadt1(increment_atomic);std::threadt2(increment_atomic);t1.join();t2.join();std::cout Counter: counter \n;return0;}4.1 基本原子类型12345#include atomicstd::atomicint atomicInt(0);// 原子整数std::atomicbool atomicBool(false);// 原子布尔值std::atomiclong atomicLong;// 默认初始化为04.2 加载和存储1234567// 存储值atomicInt.store(42);// 原子存储atomicInt 42;// 等价写法// 加载值intvalue atomicInt.load();// 原子加载value atomicInt;// 等价写法4.3 交换操作1intold atomicInt.exchange(100);// 原子交换为新值返回旧值4.4 读-修改-写操作1234567std::atomicint counter(0);// 原子加法返回旧值intprev counter.fetch_add(5);// counter 5返回加前的值// 原子减法prev counter.fetch_sub(3);// counter - 3返回减前的值12345std::atomicint flags(0);flags.fetch_or(0x01);// 原子按位或flags.fetch_and(~0x01);// 原子按位与flags.fetch_xor(0x03);// 原子按位异或4.5 比较交换 (CAS)12345678910std::atomicint value(10);intexpected 10;// 比较并交换boolsuccess value.compare_exchange_weak(expected, 20);// 如果value expected则设置为20返回true// 否则将expected更新为当前value返回false// 强版本 (较少虚假失败)success value.compare_exchange_strong(expected, 30);4.6 内存顺序 (Memory Order)12345678910111213// 默认是最严格的内存顺序 (sequential consistency)atomicInt.store(42, std::memory_order_seq_cst);// 宽松内存顺序atomicInt.store(42, std::memory_order_relaxed);// 常见内存顺序:// - memory_order_relaxed: 无顺序保证// - memory_order_consume: 数据依赖顺序// - memory_order_acquire: 读操作防止上方读写重排// - memory_order_release: 写操作防止下方读写重排// - memory_order_acq_rel: 读-修改-写操作// - memory_order_seq_cst: 顺序一致性 (默认)4.7 原子标志1234567std::atomic_flag flag ATOMIC_FLAG_INIT;// 必须这样初始化// 测试并设置 (原子操作)boolwas_set flag.test_and_set();// 清除标志flag.clear();4.8 原子指针12345678910classMyClass {};MyClass* ptr newMyClass();std::atomicMyClass* atomicPtr(ptr);// 原子指针操作MyClass* old atomicPtr.exchange(newMyClass());// 比较交换指针MyClass* expected old;atomicPtr.compare_exchange_strong(expected, nullptr);4.9 自定义原子类型123456789101112structPoint {intx;inty; };std::atomicPoint atomicPoint{Point{1, 2}};// 必须是可平凡复制的类型(trivially copyable)static_assert(std::is_trivially_copyablePoint::value,Point must be trivially copyable);// 原子操作示例Point old atomicPoint.load();// 原子读取atomicPoint.store(Point{3, 4});// 原子写入Point newVal{5, 6};Point expected{3, 4};atomicPoint.compare_exchange_strong(expected, newVal);// CAS操作std::atomic对模板类型T的关键要求是可平凡复制Trivially Copyable保证对象可以用memcpy方式安全复制无用户定义的拷贝控制析构函数、拷贝/移动构造/赋值标准布局Standard Layoutstatic_assert在编译时验证这些条件若不满足会立即报错比运行时错误更安全。一个类型T是平凡可复制Trivially Copyable的当且仅当满足以下所有条件没有用户定义的拷贝构造函数T(const T)没有用户定义的移动构造函数T(T)没有用户定义的拷贝赋值运算符T operator(const T)没有用户定义的移动赋值运算符T operator(T)有一个平凡的隐式定义的或default析构函数所有非静态成员和基类也必须是平凡可复制的不能有虚函数或虚基类如果满足这些条件编译器可以安全地使用memcpy来复制该类型的对象而不会引发未定义行为UB。5. 死锁预防当多个线程需要多个锁时可能产生死锁。预防方法总是以相同的顺序获取锁使用std::lock同时锁定多个互斥量123456789std::mutex mtx1, mtx2;voidsafe_lock() {// 同时锁定两个互斥量避免死锁std::lock(mtx1, mtx2);std::lock_guardstd::mutex lock1(mtx1, std::adopt_lock);std::lock_guardstd::mutex lock2(mtx2, std::adopt_lock);// 安全地访问共享资源}6. 线程局部存储 (thread_local)使用thread_local关键字声明线程局部变量每个线程有自己的副本。12345678910111213141516171819#include thread#include iostreamthread_localintthread_specific_value 0;voidthread_function(intid) {thread_specific_value id;std::cout Thread id : thread_specific_value \n;}intmain() {std::threadt1(thread_function, 1);std::threadt2(thread_function, 2);t1.join();t2.join();return0;}7. 读写锁读写锁是一种特殊的同步机制允许多个读操作并发执行但写操作必须独占访问。这种锁在读多写少的场景下能显著提高性能。C17 中的std::shared_mutex123456789101112131415161718192021222324252627#include shared_mutex#include vectorclassThreadSafeContainer {private:std::vectorint data;mutablestd::shared_mutex mutex;// mutable 允许const方法加锁public:// 读操作 - 使用共享锁intget(size_tindex)const{std::shared_lockstd::shared_mutex lock(mutex);returndata.at(index);}// 写操作 - 使用独占锁voidset(size_tindex,intvalue) {std::unique_lockstd::shared_mutex lock(mutex);data.at(index) value;}// 批量读操作示例std::vectorint getSnapshot()const{std::shared_lockstd::shared_mutex lock(mutex);returndata;}};读写锁特性三种访问模式共享读锁 (shared_lock)多个线程可同时持有独占写锁 (unique_lock)只有一个线程可持有升级锁 (C14没有直接支持需手动实现)锁的优先级策略读优先容易导致写线程饥饿写优先可能降低读并发度公平策略折中方案典型使用场景配置信息的热更新缓存系统高频查询低频修改的数据结构8. 自旋锁 (Spin Lock)自旋锁是一种非阻塞锁当线程无法获取锁时不会休眠而是循环检查锁状态忙等待。适用于锁持有时间极短的场景。基本自旋锁实现1234567891011121314151617181920212223#include atomicclassSpinLock {std::atomic_flag flag ATOMIC_FLAG_INIT;public:voidlock() {while(flag.test_and_set(std::memory_order_acquire)) {// 可加入CPU暂停指令减少争用时的能耗#ifdef __x86_64____builtin_ia32_pause();#endif}}voidunlock() {flag.clear(std::memory_order_release);}booltry_lock() {return!flag.test_and_set(std::memory_order_acquire);}};TTAS Backoff12345678910111213141516171819202122232425262728classAdvancedSpinLock {std::atomicbool locked{false};public:voidlock() {boolexpected false;intbackoff 1;constintmax_backoff 64;while(!locked.compare_exchange_weak(expected,true,std::memory_order_acquire, std::memory_order_relaxed)) {expected false;// compare_exchange_weak会修改expected// 指数退避for(inti 0; i backoff; i) {#ifdef __x86_64____builtin_ia32_pause();#endif}backoff std::min(backoff * 2, max_backoff);}}voidunlock() {locked.store(false, std::memory_order_release);}};总结以上为个人经验希望能给大家一个参考