如何用shared_ptr减少锁的争用
在并发环境下锁的使用是家常便饭, 如何减少锁的使用是优化程序性能的一个方面. c++11里面新增了智能指针std::shared_ptr, 这个东西也许能给我们带来些启发. shared_ptr的一个特性是当引用计数为0时,它所拥有的堆内存会被自动释放. 利用这个特性我们可以做点实用的功能, 如下程序:
#include <assert.h>
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread> std::shared_ptr<int> kNumPtr(new int(0));
std::mutex kmtx; std::shared_ptr<int> getSharedPtr()
{
kmtx.lock();
std::shared_ptr<int> ptr = kNumPtr;
kmtx.unlock();
return ptr;
} void dosomething(std::shared_ptr<int> ptr)
{
std::cout << "value: " << *ptr << std::endl;
} int main()
{ auto threadProc = [&](){
for(size_t i = 0; i < 100; ++i)
{
kmtx.lock();
if(!kNumPtr.unique()){
kNumPtr.reset(new int(*kNumPtr));
}
assert(kNumPtr.unique());
*kNumPtr = *kNumPtr + 1;
kmtx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}; std::thread t1(threadProc);
std::thread t2(threadProc);
std::thread t3(
[&](){
for(size_t i = 0; i < 100000; ++i)
{
std::shared_ptr<int> ptr = getSharedPtr();
dosomething(ptr);
}
}
); t1.join();
t2.join();
t3.join(); std::cout << "kNumPtr's value: " << *kNumPtr << std::endl;
assert(*kNumPtr = 200);
assert(kNumPtr.unique());
}
我们一共启动了三个线程, 这个程序模拟的场景是读的频率远远大于写的频率. 两个写线程模拟对共享数据的修改, 一个读线程用来模拟高频读的行为. dosomething模拟对数据的操作. 通常我们的程序需要在读操作的时候加上锁, 然而这里却只是加了一个锁用来做拷贝智能指针的操作,临界区的长度基本可以忽略, 如果dosomething的耗时很长, 比如服务器网络编程中通常的IO读写, 那么这个锁的开销其实是很大的, 对其它线程共享资源的访问性能延迟很大. 而如果换成现在的代码, 其代价几乎可以忽略.
再看写线程, 其实写线程用了copy_on_write技术, 将旧有的共享资源拷贝到新的地址空间上, 比较重要的一点是这个旧有的资源其实在reset之后 其引用计数(use_count)的值其实为0, 如果在读线程中处理完毕之后, 操作系统会自动将这份旧有内存进行释放, 这点才是真正有意思的地方.
程序地址:https://github.com/xiaopeifeng/CodeTricks/blob/master/shared_ptr_copyonwrite.cc
如何用shared_ptr减少锁的争用的更多相关文章
- The art of multipropcessor programming 读书笔记-3. 自旋锁与争用(2)
本系列是 The art of multipropcessor programming 的读书笔记,在原版图书的基础上,结合 OpenJDK 11 以上的版本的代码进行理解和实现.并根据个人的查资料以 ...
- MYSQL线程池总结(一)
线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导致资源利用率低 ...
- MyISAM 调度(优先级)的一些优化【转】
MySQL的MyISAM引擎现在越来越被淡化了,但是还是有必要再温习总结一下的. 允许你改变语句调度的优先级,它可以使来自多个客户端的查询更好地协作,这样单个客户端就不会由于锁定而等待很长时间.改变优 ...
- MySQL查询优化--细节理论
select的 high_priority还是比较有用,在实践中,平均5~6秒提高到3秒 ======================================================= ...
- mysql的mvcc(多版本并发控制)
mysql的mvcc(多版本并发控制) 我们知道,mysql的innodb采用的是行锁,而且采用了多版本并发控制来提高读操作的性能. 什么是多版本并发控制呢 ?其实就是在每一行记录的后面增加两个隐藏列 ...
- 2015第15周日PostgreSQL学习
英文版官网地址:http://www.postgresql.org/ 上面显示的最新版本信息是PostgreSQL 9.4.1, 9.3.6, 9.2.10, 9.1.15 & 9.0.19 ...
- Linux内存管理 (13)回收页面
专题:Linux内存管理专题 关键词:LRU.活跃/不活跃-文件缓存/匿名页面.Refault Distance. 页面回收.或者回收页面也即page reclaim,依赖于LRU链表对页面进行分类: ...
- (转)MYSQL线程池总结(一)
MYSQL线程池总结(一) 原文:http://www.cnblogs.com/cchust/p/4510039.html 线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应 ...
- Mysql 的InnoDB事务方面的 多版本并发控制如何实现 MVCC
Mysql的MVCC不能解决幻读的问题,但是Mysql还有间隙锁功能,Mysql的间隙锁工作在Repeatable Read隔离级别下面,可以防止幻读, 参考:Mysql 间隙锁原理,以及Repeat ...
随机推荐
- Hibernate一对一、一对多、多对多注解映射配置
一对一: 一对多: 多对多:
- r-cnn学习(八):minibatch
这段代码包括由输入图片随机生成相应的RoIs,并生成相应的blobs,由roidb得到相应的 minibatch.其代码如下. # ---------------------------------- ...
- @echo off 与echo off
echo off 关闭其他命令的显示(但是不包括自身这条命令) @echo off 关闭所有命令的显示(@关闭其后命令的显示)
- rsa 签名 加密解密
A->B 签名 ==========================A方+A方的私钥 => B收到后 用A方的公钥 验证签名 ==========================A-> ...
- 批量删除 svn文件
windows下批量删除SVN的方法 ============================ 在.svn的同级目录,也就是项目的根目录 新建文件 killsvn.bat 输入内容: @echo on ...
- stl vector erase
C++ Code 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...
- Document对象和window对象
window对象--- 代表浏览器中的一个打开的窗口或者框架,window对象会在<body>或者<frameset>每次出现时被自动创建,在客户端JavaScript中,Wi ...
- 腾讯QQ形象18年变迁史,最早的QQ企鹅形象居然长这样!
1999年,腾讯创建之初,这是当时QQ的形象,现在看起来很滑稽,又高又瘦.当时公司并没有专职的设计师,所以这个形象就凑合着用了. 后来,腾讯也觉着上一个形象做的不是特别好,于是在2000年的时候,公司 ...
- [Android Pro] 判断Uri对应的ContentProvider所操作的数据库u存在,及DownloadManager的暂停,继续
reference to : http://blog.csdn.net/u012858313/article/details/38821857 项目中遇到一个问题,就是用到DownloadManage ...
- 【Java EE 学习 23】【log4j的使用】【ant的使用】【内省】
一.ant下载地址:http://ant.apache.org/bindownload.cgi 二.log4j下载地址:http://logging.apache.org/log4j/2.x/dow ...