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

《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread

《C++ 108好库》之之2 多线程库thread,mutex,condition_variable,this_thread

  • 《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread
  • std::thread类
  • ​​互斥量(Mutex)​​类
    • std::mutex​​类
    • std::lock_guard类
    • std::unique_lock类
  • ​​条件变量(Condition Variable)​​类
  • 获取线程ID和 延时
  • 使用例子
    • 创建线程
    • 使用mutex和Condition Variable的生产者-消费者模型

《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread

C++11 中,多线程编程通过标准库 正式引入,提供了跨平台的线程管理能力。
多线程一般由这些类合作构成:std::thread类、std::mutex​​类、std::lock_guard类、 std::unique_lock类、condition_variable类

std::thread类

1 ​​创建线程​​
explicit thread(_Callable&& __f, _Args&&… __args)
使用 std::thread类创建线程,构造函数接受函数对象及参数:
向线程函数传递参数时,参数会被复制到线程的独立内存中;如果希望传递引用,需要使用std::ref。

2​​线程管理​​:
join():等待线程完成。
detach():将线程与主线程分离,使其独立运行。一旦分离,就不能再与之通信。
注意:在销毁std::thread对象之前,必须调用join()或detach(),否则程序会终止(调用std::terminate)。

​​互斥量(Mutex)​​类

C++11提供了std::mutex用于保护共享数据,防止数据竞争。

std::mutex​​类

std::mutex()

std::mutex::lock() :调用此函数会尝试​​锁定​​互斥体。
行为:​​如果互斥体当前​​未被任何线程锁定​​,则调用线程获得锁,函数立即返回。如果互斥体​​已被其他线程锁定​​,则调用线程会被​​阻塞​​(挂起),直到持有锁的线程解锁该互斥体。一旦解锁,等待的线程之一(取决于调度)会获得锁并继续执行。
​​特点:​​ 阻塞调用。如果忘记解锁会导致死锁。
​​用法:​​ 当你需要确保临界区被独占访问,并且可以接受线程阻塞等待时使用。

std::mutex::try_lock(): 调用此函数会​​尝试​​锁定互斥体,但​​不会阻塞​​调用线程。
​​行为:​​如果互斥体当前​​未被锁定​​,则调用线程获得锁,函数返回 true。如果互斥体​​已被锁定​​(无论是当前线程还是其他线程),则函数​​立即返回 false​​,线程继续执行而不会被阻塞。
​​特点:​​ 非阻塞调用。需要检查返回值来判断是否成功获得锁。
​​用法:​​ 当你需要在锁不可用时做其他事情,避免阻塞线程时使用。常用于轮询、避免死锁策略(如按固定顺序获取多个锁失败时释放已持有的锁)或非关键路径的优化。

std::mutex::unlock():解锁

std::lock_guard类

它在构造时自动锁定给定的互斥体,并在析构时(通常是离开作用域时)自动解锁它。
​​构造时:​​ 调用传入的互斥体(如 std::mutex)的 lock()方法。这会阻塞直到获得锁。
​​析构时:​​ 调用互斥体的 unlock()方法。
用法:std::lock_guardstd::mutex lock(mtx); // 构造时自动调用 mtx.lock()

std::unique_lock类

功能比 lock_guard​​更强大、更灵活​​。它也管理互斥体的锁定和解锁,但提供了更多的控制选项。
​​行为/特点:​​
​​灵活的构造:​​默认构造:创建一个不关联任何互斥体的 unique_lock。
关联互斥体并立即锁定(阻塞):unique_lock lock(mtx);(等价于 lock_guard)
关联互斥体但​​延迟锁定​​:unique_lock lock(mtx, std::defer_lock);构造时不锁定,稍后手动调用 lock(), try_lock()或 try_lock_for()/try_lock_until()(针对 std::timed_mutex)。
关联互斥体并尝试锁定:unique_lock lock(mtx, std::try_to_lock);构造时调用 mtx.try_lock()。
关联互斥体并假设已锁定(接管所有权):unique_lock lock(mtx, std::adopt_lock);假设调用线程已经持有 mtx的锁,unique_lock负责后续解锁。
手动控制:​​
lock(): 阻塞锁定关联的互斥体(如果尚未锁定)。
try_lock(): 尝试非阻塞锁定关联的互斥体。
unlock(): ​​手动解锁​​关联的互斥体,在 unique_lock析构前可以临时释放锁(这在 lock_guard中是不可能的)。析构时如果互斥体仍被该 unique_lock持有,会自动解锁。
release(): 释放对互斥体的所有权管理(返回互斥体指针),不再负责解锁。调用者需手动管理。
​​所有权:​​
可移动 (std::move),但不可复制。锁的所有权可以在 unique_lock对象之间转移。
​​条件变量:​​ std::condition_variable::wait等函数​​必须​​使用 std::unique_lockstd::mutex作为参数,因为它需要能在等待时解锁和重新锁定互斥体(这是 lock_guard做不到的)。

​​条件变量(Condition Variable)​​类

<condition_variable>
用于线程间的同步,允许线程在某些条件不满足时休眠,直到被其他线程通知。通常与互斥量一起使用。
void notify_one() noexcept;
void notify_all() noexcept;
wait(unique_lock& __lock) noexcept;
wait_until(unique_lock& __lock,const chrono::time_point<__clock_t, _Duration>& __atime)
wait_for(unique_lock& __lock, const chrono::duration<_Rep, _Period>& __rtime)

获取线程ID和 延时

std::this_thread里的函数
inline thread::id get_id()
获取​​当前执行线程的唯一标识符​​。
std::thread::id main_id = std::this_thread::get_id(); // 输出示例:0x70000a15c000

inline void sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
使​​当前线程阻塞​​一段指定的​​相对时间​​。
std::this_thread::sleep_for(std::chrono::seconds(1));

inline void sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
使​​当前线程阻塞​​直到​​绝对时间点​​。

使用例子

创建线程

std::thread thread_hello(hello,"LiHua");
thread_hello.join();

传入函数给线程
void hello(const std::string str) {
std::cout << "hello world! "<<str<<std::endl;
}

使用mutex和Condition Variable的生产者-消费者模型

std::thread thread_producer(producer);
thread_producer.detach();std::thread thread_consumer(consumer);
thread_consumer.join();

其中的线程函数

std::queue<int> dataQueue;
std::mutex mtx_test_thread;
std::condition_variable cv_test_thread;
void producer() {for (int i = 0; i < 50; ++i) {{std::lock_guard<std::mutex> lock(mtx_test_thread);dataQueue.push(i); std::cout << "push:" << i << std::endl;}std::this_thread::sleep_for(std::chrono::seconds(1));cv_test_thread.notify_one(); // 通知消费者}
}void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx_test_thread);cv_test_thread.wait(lock, [] { return !dataQueue.empty(); });int value = dataQueue.front();dataQueue.pop();lock.unlock();if (value == -1) break; // 终止条件std::cout << "Consumed: " << value << std::endl;}
}

文章转载自:

http://7NMfTv6a.trkhx.cn
http://dVUWZ7EU.trkhx.cn
http://YzsxrYeS.trkhx.cn
http://izVIk6ZA.trkhx.cn
http://Zngg5WpE.trkhx.cn
http://x2msPq1c.trkhx.cn
http://aqtwpDcM.trkhx.cn
http://6XHlIKet.trkhx.cn
http://Orq0LHxt.trkhx.cn
http://OZ3KbLyP.trkhx.cn
http://u7TkmnCy.trkhx.cn
http://387S5W1D.trkhx.cn
http://6POc9kek.trkhx.cn
http://rhr9SLXX.trkhx.cn
http://lCvWR0dS.trkhx.cn
http://x9djfv0u.trkhx.cn
http://XMb6VRX0.trkhx.cn
http://M5Y9XI2z.trkhx.cn
http://vZdjWHZf.trkhx.cn
http://PFg74mHP.trkhx.cn
http://9WK0DB4F.trkhx.cn
http://hJLYNbPI.trkhx.cn
http://QLG3tmRN.trkhx.cn
http://Bcxnv8Fi.trkhx.cn
http://Jrebqri4.trkhx.cn
http://ltt4SG3R.trkhx.cn
http://sB3h2L0U.trkhx.cn
http://JnNBaxID.trkhx.cn
http://eME7TVCa.trkhx.cn
http://82hZPal4.trkhx.cn
http://www.dtcms.com/a/377785.html

相关文章:

  • 【超级工程·蓝燕云】雅鲁藏布江水电站如何攻克“不可能完成”的工程?
  • 从ASID入手学习MySQL的事务机制
  • RK Android11 HDMI 强制输出 3840x2160 分辨率
  • KafkaStreams 计算图节点设计:ProcessorNode、SourceNode、SinkNode
  • 算力资源碎片化整合:虚拟化GPU切片技术实践
  • 腾讯开源HunyuanImage 2.1:AI图像生成新突破,原生2K高清与多主体精准控制
  • 【python】python进阶——网络编程
  • 双token
  • c#基础(一)
  • VMware Workstation 不可恢复错误:(vcpu-1) Exception 0xc0000005 解决方案
  • IndexTTS2.0_ 情感表达与时长可控的自回归零样本语音合成突破
  • Git提交文件提取工具:一键将特定提交的文件导出到指定目录
  • 中间件漏洞详解
  • TC_Motion多轴运动-PID调节
  • Java 学习笔记(进阶篇3)
  • 金蝶云星空 调价表取历史价格
  • TwinCAT3人机界面1
  • C#语言入门详解(18)传值、输出、引用、数组、具名、可选参数、扩展方法
  • 【C++世界之string模拟实现】
  • 打工人日报#20250910
  • LeetCode100-206反转链表
  • function-call怎么训练的,预料如何构建
  • OpenLayers数据源集成 -- 章节四:矢量格式图层详解
  • 220V供电遥测终端 220V供电测控终端 选型
  • 【LLM】Transformer注意力机制全解析:MHA到MLA
  • 三十六、案例-文件上传-阿里云OSS-集成
  • 网编.hw.9.10
  • 4215kg轻型载货汽车变速器设计cad+设计说明书
  • Python数据可视化科技图表绘制系列教程(七)
  • 【 VMware Workstation 提示“虚拟机已在使用”怎么办?一篇文章彻底解决!】