C++11的mutex和lock_guard,muduo的MutexLock 与MutexLockGuard
互斥锁是用来保护一段临界区的,它可以保证某段时间内只有一个线程在执行一段代码或者访问某个资源。
C++11的mutex和lock_guard
C++11新增了mutex,使用方法和linux底下的常用使用方法差不多。先使用std::mutex 定义一个互斥锁,例如std::mutex XXXmutex在需要使用互斥锁的时候,使用XXXmutex.lock();上锁,以及使用XXXmutex.unlock();
解锁。下面是一段参考代码:
#include <iostream>
#include <map>
#include <string>
#include <chrono>
#include <thread>
#include <mutex>
std::map<std::string, std::string> g_pages;
std::mutex g_pages_mutex;
void save_page(const std::string &url)
{
// simulate a long page fetch
std::this_thread::sleep_for(std::chrono::seconds(2));
std::string result = "fake content";
g_pages_mutex.lock();
g_pages[url] = result;
g_pages_mutex.unlock();
}
int main()
{
std::thread t1(save_page, "http://foo");
std::thread t2(save_page, "http://bar");
t1.join();
t2.join();
g_pages_mutex.lock(); // not necessary as the threads are joined, but good style
for (const auto &pair : g_pages) {
std::cout << pair.first << " => " << pair.second << '\n';
}
g_pages_mutex.unlock();
}
t2.join();
}
使用mutex的时候需要手动上锁还有解锁,C++11提供了另一个利器–>lock_guard,它是与mutex配合使用,把锁放到lock_guard中时,mutex自动上锁,lock_guard析构时,同时把mutex解锁。使用的应该就是所谓的RAII技法(RAII,,也称为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单的说,RAII 的做法是使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构的时候释放资源。)
下面是另一段示例代码:
#include <thread>
#include <mutex>
int g_i = 0;
std::mutex g_i_mutex; // protects g_i
void safe_increment()
{
std::lock_guard<std::mutex> lock(g_i_mutex);
++g_i;
// g_i_mutex is automatically released when lock
// goes out of scope
}
int main()
{
std::thread t1(safe_increment);
std::thread t2(safe_increment);
t1.join();
t2.join();
}
使用lock_guard的时候不需要手动解锁,资源获取即初始化,析构的时候就会自动解锁,使用起来会相对比较方便。
muduo的MutexLock 与MutexLockGuard
muduo库里面也封装了两个类似的类:MutexLock 与MutexLockGuard。
MutexLock 封装临界区(critical section),这是一个简单的资源类,用RAII 手法[CCS,条款13] 封装互斥器的创建与销毁。临界区在Windows 上是struct CRITICAL_SECTION,是可重入的;在Linux 下是pthread_mutex_t,默认是不可重入的。MutexLock 一般是别的class 的数据成员。
MutexLockGuard 封装临界区的进入和退出,即加锁和解锁。MutexLockGuard 一般是个栈上对象,它的作用域刚好等于临界区域。
MutexLockGuard类使用RAII技法封装,在实际应用中这个类更常用,作为class 数据成员的MutexLock 只能用于同步本class 的其他数据成员的读和写,它不能保护安全地析构。因为MutexLock 成员的生命期最多与对象一样长,而析构动作可说是发生在对象身故之后(或者身亡之时)。
使用方法:muduo的MutexLock 与MutexLockGuard使用方法也是很简单的,MutexLockGuard负责加锁解锁,MutexLock 封装临界区,所以MutexLockGuard需要和MutexLock 配合使用,一般应先使用MutexLock定义一个临界区,然后将该MutexLock作为参数传进MutexLockGuard对象,例如:
MutexLock mutex_;//互斥锁
MutexLockGuard lock(mutex_);
这样在MutexLockGuard对象生命期结束的时候会自动解锁。那么他的生命期什么时候结束呢?一般如果只是上锁一小段代码,而该代码后面还有很多的语句,那么可以使用大括号将想要锁定的区域括起来。
C++11的mutex和lock_guard,muduo的MutexLock 与MutexLockGuard的更多相关文章
- 基于std::mutex std::lock_guard std::condition_variable 和std::async实现的简单同步队列
C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为.通常的做法是在修改共享数据成员的时候进行加锁--mutex.在使用锁的时候通 ...
- 39.mutex 的lock_guard与unique_lock
#include <iostream> #include <thread> #include <mutex> using namespace std; #defin ...
- C++ 11 多线程下std::unique_lock与std::lock_guard的区别和用法
这里主要介绍std::unique_lock与std::lock_guard的区别用法 先说简单的 一.std::lock_guard的用法 std::lock_guard其实就是简单的RAII封装, ...
- C++11 并发指南三(std::mutex 详解)
上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::thread 的一些用法,并给出了两个小例子,本文将介绍 std::mutex 的用法. Mutex ...
- C++11并发——多线程std::mutex (二)
https://www.cnblogs.com/haippy/p/3237213.html Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mute ...
- C++11中的mutex, lock,condition variable实现分析
本文分析的是llvm libc++的实现:http://libcxx.llvm.org/ C++11中的各种mutex, lock对象,实际上都是对posix的mutex,condition的封装.不 ...
- C++11 并发指南三(std::mutex 详解)(转)
转自:http://www.cnblogs.com/haippy/p/3237213.html 上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::th ...
- 【C/C++开发】C++11 并发指南三(std::mutex 详解)
本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C ...
- C++11 并发指南三(Lock 详解)
在 <C++11 并发指南三(std::mutex 详解)>一文中我们主要介绍了 C++11 标准中的互斥量(Mutex),并简单介绍了一下两种锁类型.本节将详细介绍一下 C++11 标准 ...
随机推荐
- 34.3 转换流 InputStreamReader OutStreamReader
转换流: 把字节输出流转换成字符输出流 标准输入输出流:传输的对象是字节流 System.in . System.out 标准输入输出流 public static final InputStream ...
- Struts2-学习笔记系列(13)-类型转换异常和校验器
Struts2框架有默认的类型转换错误拦截机制,该配置在struts-default.xml中,名叫conversionError,但是想使用需要继承ActionSupport. 默认的错误提示信息是 ...
- ConcurrentHashMap和 CopyOnWriteArrayList提供线程安全性和可伸缩性 以及 同步的集合类 Hashtable 和 Vector Collections.synchronizedMap 和 Collections.synchronizedList 区别缺点
ConcurrentHashMap和 CopyOnWriteArrayList提供线程安全性和可伸缩性 DougLea的 util.concurrent 包除了包含许多其他有用的并发构造块之外,还包含 ...
- 最近遇到adb connection 问题,总结一下
最近eclipse总是遇到adb connection问题,网上搜索了一些解决方法,在cmd tool工具下adb kill-server ,adb start-server ,甚至重启都无效.然后我 ...
- 移动硬盘临时文件太多怎么办,python黑科技帮你解决
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 星安果 PS:如果想了解更多关于python的应用,可以私信我,或者 ...
- Mac 安装 brew(最新教程,绝对可行)
现在安装brew,一会报这个错,一会儿报那个错,上网查了很多教程,用了很多时间都是不可以,电脑开VPN翻墙也不行. Warning: The Ruby Homebrew installer is no ...
- 使用redis-dump与redis-load方式迁移redis数据库
实际生产场景中,有可能会因为迁移机房或者更换物理机等原因需要在生产环境迁移redis数据.本文就来为大家介绍一下迁移redis数据的方法. 迁移redis数据一般有如下3种方式: 1.第三方工具red ...
- [V&N2020 公开赛]TimeTravel 复现
大佬友链(狗头):https://www.cnblogs.com/p201821440039/ 参考博客: https://www.zhaoj.in/read-6407.html https://cj ...
- 关于对vue-router的优化(详尽版)
这两天总结了关于vue-router优化的几点技法,做个笔记 在基于vue的移动端app中,通过vue-router可以便捷的进入某一路由或回退到上一路由,但是若不对vue-router做相关优化处理 ...
- 解决利用hibernate连接mysql时无法插入汉字的问题
1.先修改mysql数据库的配置文件my.ini,此文件放在mysql安装文件的根目录下.找到default-character-set属性,并将其值更改为utf8(不是utf-8),将default ...