
C++11 多线程并发编程,thread,lock,lock_guard,unique_lock使用
互斥量(
使用
发布日期:2021-05-10 01:23:25
浏览次数:19
分类:精选文章
本文共 4397 字,大约阅读时间需要 14 分钟。
thread类与多线程编程
在C++中,thread
类是进行多线程编程的核心工具,可以通过它创建和管理子线程。了解thread
类的成员函数和使用方法,是掌握多线程编程的基础。
thread成员函数解析
join()
方法
join()
方法用于阻塞主线程,等待子线程执行完成。如果子线程已经完成或被终止,join()
立即返回。 detach()
方法
detach()
方法取消主线程与子线程之间的关联,子线程独立执行。主线程会等到所有子线程完成后自动退出。 joinable()
方法
joinable()
返回一个布尔值,用于检查当前线程是否可以被另一个线程阻塞等待。可以通过反复调用该方法判断线程状态。 id()
方法
id()
方法用于获取当前线程的内核线程ID,用于排查线程相关问题或在调试中跟踪线程。 互斥量(mutex
)的使用
互斥量是实现线程安全的核心机制。使用互斥量控制共享资源的访问,避免竞态条件和死锁。
<mutex>
概述
互斥量有两种主要功能:
lock()
和unlock()
:加锁和解锁操作。- 原子操作:确保在加锁和解锁期间,资源的访问是安全的。
互斥量的加锁与解锁
使用std::lock_guard
std::lock_guard
是一个类模板,可以替代传统的lock()
和unlock()
。它的构造在加锁,析构在解锁。 std::lock()
函数
std::lock()
用于加多个互斥量锁。如果所有锁都加锁,才会成功。否则,返回不加锁。 std::try_to_lock
策略
std::unique_lock
中,std::try_to_lock
是另一个加锁方式,可以尝试加锁,如果失败则直接返回,不阻塞。 unique_lock的灵活性
std::unique_lock
提供了更强的灵活性,支持以下参数:
adopt_lock
:将现有的锁 hObject转移所有权。try_to_lock
:非阻塞加锁方式。defer_lock
:无需提前加锁,直接放置unique_lock
对象。
unique_lock的成员函数
lock()
:阻塞加锁,与std::lock()
类似。unlock()
:手动解锁。try_lock()
:非阻塞加锁。release()
:释放unique_lock
管理的互斥量,转移所有权。
unique_lock的所有权转移
unique_lock
支持将互斥量的所有权转移到另一个unique_lock
对象。可以通过std::move
操作符或构造函数完成。
sleep方法
在多线程编程中,有时需要让线程暂停一定时间,使用std::this_thread::sleep_for
或sleep_until
。
#include// 阻塞2秒std::chrono::milliseconds delay(2000);std::this_thread::sleep_for(delay);
代码示例
下面是一个简单的多线程示例:
#include#include #include using namespace std;class B {private: queue que; mutex my_mutex; condition_variable cond;public: void insert() { for (int i = 0; i < 1000; ++i) { { lock_guard guard(my_mutex); que.push(i); cond.notify_one(); } // 不加锁的可见界面 } } void pop() { while (!que.empty()) { { lock_guard guard(my_mutex); int num = que.front(); que.pop(); // 可以手动解锁或由unique_lock自动解锁 } // 可以等待或不等待 } } }; int main() { B b; thread insert_thread(&B::insert, &b); thread pop_thread(&B::pop, &b); insert_thread.join(); pop_thread.join(); cout << "完成" << endl; return 0; }
条件变量的使用
条件变量提供了一种有效的等待机制。通过与互斥量和条件变量组合,可以实现线程间的同步与通信。
#include#include #include using namespace std;class A {public: vector vec; mutex mutex; condition_variable cond; void produce() { for (int i = 0; i < 100; ++i) { { lock_guard guard(mutex); vec.push_back(i); cond.notify_one(); } // 可以添加其他操作 } } void consume() { while (!vec.empty()) { { lock_guard guard(mutex); int num = vec.front(); vec.pop(); cout << "消费了:" << num << endl; // 可以添加其他操作 } // 手动释放 } } }; int main() { A a; thread produce_thread(&A::produce, &a); thread consume_thread(&A::consume, &a); produce_thread.join(); return 0; }
originalTask完成后
这个系统中的任务可能是耗时的,需要确保其能完成。如果任务长时间未完成,可以使用原子操作来跟踪和管理。
#include#include #include using namespace std;class Task {private: atomic count; mutex mutex;public: Task() : count(0) {} void run() { for (int i = 0; i < 100000; ++i) { { lock_guard guard(mutex); count++; } } } int get_count() { lock_guard guard(mutex); return count; } }; int main() { Task t; thread t_thread(&Task::run, &t); t_thread.join(); cout << "跑完一个循环,计数器:" << t.get_count() << endl; return 0; }
使用std::async
std::async
用于创建asynchronous Task。我们可以根据需求选择不同的策略:
std::launch::async
:立即创建新线程执行任务。std::launch::deferred
:延迟执行任务,等到get()
或wait()
被调用。
#include#include #include #include using namespace std;struct MyTask { MyTask(int delay) : delay_(delay) {} // 仅存在于lambda表达式中区域 ~MyTask() {} void operator()() const { cout << "任务执行完毕" << endl; }private: int delay_;};int main() { auto task = make_unique (2000); // 创建一个asynchronous Task // std::launch可以选择策略 auto result = async(task, launch::async); result.wait_for(1s); cout << "已获取到结果" << endl; return 0;}
以上示例展示了如何在多线程中安全地管理共享资源、传递任务,以及如何进行异步操作。通过合理使用互斥量和条件变量,可以实现线程安全和高效的任务管理。
发表评论
最新留言
很好
[***.229.124.182]2025年03月31日 07时00分45秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
HTTP协议状态码详解(HTTP Status Code)
2019-03-06
JMeter 中实现发送Java请求
2019-03-06
设计模式点滴
2019-03-06
数据库优化
2019-03-06
[备忘]域用户登陆出现“此工作站和主域间的信任关系失败”错误解决方法
2019-03-06
继续聊WPF——用Blend自定义Listview控件的列表头
2019-03-06
【WPF】制作自定义的列表项面板
2019-03-06
【.net 深呼吸】启动一个进程并实时获取状态信息
2019-03-06
OO_Unit2 多线程电梯总结
2019-03-06
json-lib的使用《二》
2019-03-06
LeetCode52题,别再问我N皇后问题了
2019-03-06
简单实用算法——字节位序反转
2019-03-06
webpack之带有可自动打开浏览器及热重载的基本配置
2019-03-06
前端的批量接口如何快速响应?有没有通用解决方案?
2019-03-06
Shader 入门笔记(一) 如何学习shader
2019-03-06
Huffman树及其编解码
2019-03-06
分布式、高并发、高性能场景(抢购、秒杀、抢票、限时竞答)数据一致性解决方案
2019-03-06
淘宝镜像
2019-03-06
20.波利亚过程
2019-03-06