在并发环境下锁的使用是家常便饭, 如何减少锁的使用是优化程序性能的一个方面. 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减少锁的争用的更多相关文章

  1. The art of multipropcessor programming 读书笔记-3. 自旋锁与争用(2)

    本系列是 The art of multipropcessor programming 的读书笔记,在原版图书的基础上,结合 OpenJDK 11 以上的版本的代码进行理解和实现.并根据个人的查资料以 ...

  2. MYSQL线程池总结(一)

    线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导致资源利用率低 ...

  3. MyISAM 调度(优先级)的一些优化【转】

    MySQL的MyISAM引擎现在越来越被淡化了,但是还是有必要再温习总结一下的. 允许你改变语句调度的优先级,它可以使来自多个客户端的查询更好地协作,这样单个客户端就不会由于锁定而等待很长时间.改变优 ...

  4. MySQL查询优化--细节理论

    select的 high_priority还是比较有用,在实践中,平均5~6秒提高到3秒 ======================================================= ...

  5. mysql的mvcc(多版本并发控制)

    mysql的mvcc(多版本并发控制) 我们知道,mysql的innodb采用的是行锁,而且采用了多版本并发控制来提高读操作的性能. 什么是多版本并发控制呢 ?其实就是在每一行记录的后面增加两个隐藏列 ...

  6. 2015第15周日PostgreSQL学习

    英文版官网地址:http://www.postgresql.org/ 上面显示的最新版本信息是PostgreSQL 9.4.1, 9.3.6, 9.2.10, 9.1.15 & 9.0.19 ...

  7. Linux内存管理 (13)回收页面

    专题:Linux内存管理专题 关键词:LRU.活跃/不活跃-文件缓存/匿名页面.Refault Distance. 页面回收.或者回收页面也即page reclaim,依赖于LRU链表对页面进行分类: ...

  8. (转)MYSQL线程池总结(一)

    MYSQL线程池总结(一)  原文:http://www.cnblogs.com/cchust/p/4510039.html 线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应 ...

  9. Mysql 的InnoDB事务方面的 多版本并发控制如何实现 MVCC

    Mysql的MVCC不能解决幻读的问题,但是Mysql还有间隙锁功能,Mysql的间隙锁工作在Repeatable Read隔离级别下面,可以防止幻读, 参考:Mysql 间隙锁原理,以及Repeat ...

随机推荐

  1. WCF 定义SOAP和REST风格的webservice

    摘抄于其他帖子,在此记录以备后用. 1. 定义服务数据契约(SOAP与REST方式相同)  public class Employee   { [DataMember]       public st ...

  2. Angularjs 双向绑定机制解析

    文章转自:http://www.2cto.com/kf/201408/327594.html AngularJs 的元素与模型双向绑定依赖于循环检测它们之间的值,这种做法叫做脏检测,这几天研究了一下其 ...

  3. MySQL 5.7 学习:新增配置参数

    背景: 继上次介绍 初识 MySQL 5.6 新功能.参数完之后,刚好MySQL 5.7又GA了,在官方测试里看到,MySQL5.7在功能.性能.可用性.安全和监控上又提升了很高.现在看看和MySQL ...

  4. C#实现K-MEDOIDS聚类算法

    1.任意选取K个对象作为初始聚类中心(O1,O2,…Oi…Ok). 2)将余下的对象分到各个类中去(该对象与哪一个聚类中心最近就被分配到哪一个聚类簇中): 3)对于每个类(Oi)中,顺序选取一个Or, ...

  5. c/c++ printf

    %d int %s string %p point值 %c char %lu long unsigned int

  6. sql 列转行

    原表:转过的表: 代码: ) set @sql = 'select AssetRecordId ' select @sql = @sql + ' , max(case ExtendName when ...

  7. Java笔记:对象,方法,类

    1.数据类型(类) 对象名; 这里要求数据类型必须为复合数据类型,基本数据类型声明的结构只能称为变量,而不能称为对象. 对象的初始化 对象名= new 构造方法(参数); 2.方法: 访问控制符 [修 ...

  8. iOS开发 iOS10推送必看(基础篇)

    iOS10更新之后,推送也是做了一些小小的修改,下面我就给大家仔细说说.希望看完我的这篇文章,对大家有所帮助.   原文链接   一.简单入门篇---看完就可以简单适配完了相对简单的推送证书以及环境的 ...

  9. 无法从“char*转换为“LPCWSTR”

    解决办法: 第一种方法:工程属性->配置属性->右边 项目默认值->字符集 改为未设置 第二种:一般直接加个L在前面,当是字符串常量的时候可以这样,也可以_T(x)等   来自:软件 ...

  10. 当年只会C# 所以写C++就成这样了!

    这应该是4-5年前了. 当年之会c#敲敲代码也不会C++但深信开发这东西只要思想有了. 只是语法问题. 对于C++这貌似只有大牛才能胜任的,而对于我来说是如此困难. 所以想想办法搞了很多通用类来避免C ...