在并发环境下锁的使用是家常便饭, 如何减少锁的使用是优化程序性能的一个方面. 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. Apache curator-client详解

    Apache curator框架中curator-client组件可以作为zookeeper client来使用,它提供了zk实例创建/重连机制等,简单便捷.不过直接使用curator-client并 ...

  2. Xcode 此证书签发者无效

    1.https://developer.apple.com/certificationauthority/AppleWWDRCA.cer 安装此证书 2.在keychains里选择login,然后点选 ...

  3. C#导出涉及行列合并的复杂的Excel数据

    一.导出数据格式 二.实现代码 /// <summary> /// 导出经费统计excel表格 /// </summary> /// <param name=" ...

  4. python习题 (1):login

    #!/uer/bin/env python # _*_ coding: utf-8 _*_ import sys retry_limit = 3 retry_count = 0 account_fil ...

  5. 继承的小DEMO

    代码如下 Student.java package four.com; public class Student extends Person { // private String name; // ...

  6. ASP.NET知识总结(2.对比Get和Post提交方式)

    2.对比Get和Post提交方式 get:<1>在地址栏中通过?key1=value1&key2=value2...的方式传值 <2>传递的数据用户可以直接在url中看 ...

  7. 51nod1073(约瑟夫环)

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1073 题意: 中文题诶~ 思路: 直接模拟的话O(n*k)的 ...

  8. Java小知识--length,length(),size()方法详细介绍

    Java中length,length(),size()区别 length属性:用于获取数组长度. eg: int ar[] = new int{1,2,3} /** * 数组用length属性取得长度 ...

  9. 【Java EE 学习 32 下】【JQuery】【JQuey中的DOM操作】

    一.JQuery中的DOM操作. 什么是DOM:DOM是一中和浏览器.平台.语言无关的接口,使用该接口可以轻松访问页面中所有的标准组件.DOM简称文档对象模型,是Document Oject Mode ...

  10. PAT A 1115. Counting Nodes in a BST (30)【二叉排序树】

    题目:二叉排序树,统计最后两层节点个数 思路:数组格式存储,insert建树,dfs遍历 #include<cstdio> #include<iostream> #includ ...