再看copy_on_write缩小临界区的例子
本例子是模拟的读者写者问题,采用shared_ptr+写时拷贝实现,其中我觉得一个比较值得注意的地方是考虑到对象可能在临界区析构而将析构移除临界区,这对于多线程来说要多看多思。
#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<vector>
#include<assert.h>
#include<boost/shared_ptr.hpp>
#include<boost/weak_ptr.hpp>
#include<boost/noncopyable.hpp>
using namespace std;
using namespace boost;
class Mutex:public noncopyable{//互斥量的封装
public:
Mutex(){
pthread_mutex_init(&mutex,NULL);
}
void lock(){
pthread_mutex_lock(&mutex);
}
void unlock(){
pthread_mutex_unlock(&mutex);
}
~Mutex(){
pthread_mutex_destroy(&mutex);
}
pthread_mutex_t* getMutex(){
return &mutex;
}
private:
mutable pthread_mutex_t mutex;
};
class MutexLockGuard:noncopyable{//RAII管理互斥量
public:
explicit MutexLockGuard(Mutex& mutex):mutex_(mutex){
mutex_.lock();
}
~MutexLockGuard(){
mutex_.unlock();
}
private:
Mutex& mutex_;//注意是引用,Mutex继承了noncopyable后不能拷贝构造
};
class test:noncopyable{
public:
test():ptr(new vector<int>),mutex(){}
void show(){
shared_ptr<vector<int> > temp=get();
for(vector<int>::iterator it=temp->begin();it!=temp->end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
void add(int x){//添加一个元素
MutexLockGuard guard(mutex);
if(!ptr.unique()){
shared_ptr<vector<int> > temp(new vector<int>(*ptr));
ptr.swap(temp);
}
assert(ptr.unique());
ptr->push_back(x);
}
void add(vector<int> &x){//替换整个容器
shared_ptr<vector<int> > temp(new vector<int>(x));
if(temp){
MutexLockGuard guard(mutex);
ptr.swap(temp);//不使用ptr=temp的原因是旧的容器可能在此析构(没有读者,就只有一个写者在此处),那么临界区可能由于对象析构而变大,所以采用swap使可能的析构移除到临界区外....这个技术尤其重要...
}//此后可能析构对象
}
shared_ptr<vector<int> > get(){
return ptr;
}
private:
mutable Mutex mutex;
shared_ptr<vector<int> > ptr;//采用shared_ptr管理容器
};
shared_ptr<test> globalPtr(new test);
void* worker1(void* arg){
sleep(1);
globalPtr->show();
sleep(1);
globalPtr->show();
}
void* worker2(void* arg){
globalPtr->add(10);//添加一个元素
sleep(2);
vector<int> temp(1,100);
globalPtr->add(temp);//替换整个容器
}
int main(){
pthread_t pid1,pid2;
pthread_create(&pid1,NULL,worker1,NULL);
pthread_create(&pid2,NULL,worker2,NULL);
pthread_join(pid1,NULL);
pthread_join(pid2,NULL);
return 0;
}
程序输出:
10
100
再看copy_on_write缩小临界区的例子的更多相关文章
- mysql索引设计的注意事项(大量示例,收藏再看)
mysql索引设计的注意事项(大量示例,收藏再看) 目录 一.索引的重要性 二.执行计划上的重要关注点 (1).全表扫描,检索行数 (2).key,using index(覆盖索引) (3).通过ke ...
- 再看Ajax
再回顾Ajax相关的内容,再次梳理学习还是很有必要的,尤其是实际的开发中,ajax更是必不可少,仔细学习以便避免不必要的错误. 文章导读: --1.使用XMLHttpRequest---------- ...
- 再看ftp上传文件
前言 去年在项目中用到ftp上传文件,用FtpWebRequest和FtpWebResponse封装一个帮助类,这个在网上能找到很多,前台使用Uploadify控件,然后在服务器上搭建Ftp服务器,在 ...
- 再看 AspriseOCR - OCR应用开发 -20151124
再看 AspriseOCR - OCR应用开发 我写这个博文时间为 2015/11/24日,注意时间因为,网上很多文章时间上很久远,有的已经不能参考了 很多人面对从图片中识别文字或者数字0~9 A~ ...
- Android菜鸟的成长笔记(17)—— 再看Android中的Unbounded Service
原文:Android菜鸟的成长笔记(17)-- 再看Android中的Unbounded Service 前面已经写过关于startService(Unbounded Service)的一篇文章:&l ...
- 再看case语句
再看case语句,case语句只处理单条记录,而不是set 列名的使用,可以当做数值来使用: case when 后面简直是完美的的,什么东西都是能放的,只要是一个逻辑上的true/false的逻辑就 ...
- android 智能指针的学习先看邓凡平的书扫盲 再看前面两片博客提升
android 智能指针的学习先看邓凡平的书扫盲 再看前面两片博客提升
- python基础----再看property、描述符(__get__,__set__,__delete__)
一.再看property 一个静态属性property ...
- perf使用的问题,再看perf record,perf record 设置的采样频率,采样频率是如何体现在
当perf stat -e branches 是统计 再看perf record,perf record是为了是记录时间发生的时候的调用栈, 在我的测试代码中总共有200,000,000条branch ...
随机推荐
- hdu 3033(好题,分组背包)
I love sneakers! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- BZOJ.3680.吊打XXX(模拟退火/爬山算法)
题目链接 一个比较好的解释? 模拟退火(Simulated Annealing,SA): (1)初始化一个温度(充分大).初始解状态S.每个T值的迭代次数. (2)对i=1,...,L,做(3)至(7 ...
- hdu 4562 dp ***
题意:给出一个点p(X,Y)以及若干圆.从中选出尽可能多的圆满足:圆能且只能包含p或者原点中的一个(不能在圆上):圆之间不能相交或者相切. 链接:点我 用dp求满足条件包含一个点圆的最多数目,然后两个 ...
- [工具]GitHub上整理的一些工具[转]
技术站点 Hacker News:非常棒的针对编程的链接聚合网站 Programming reddit:同上 MSDN:微软相关的官方技术集中地,主要是文档类 infoq:企业级应用,关注软件开发领域 ...
- springmvc学习总结(二) -- maven+springmvc+spring+mybatis+mysql详细搭建整合过程讲解
@_@ 写在最前 之前分享过下面这几篇: mybatis学习笔记(五) -- maven+spring+mybatis从零开始搭建整合详细过程(上)(附demo和搭建过程遇到的问题解决方法) myba ...
- HDU 4764 Stone (2013长春网络赛,水博弈)
Stone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- [转载]vs2017与docker
基本需求 系统 win10 vs2017 docker 步骤 1.开启系统的hyper-v 2. 重启电脑 3.安装docker 下载地址:https://docs.docker.com/docker ...
- Snmp学习总结(六)——linux下安装和配置SNMP
一.安装SNMP 1.1.下载Net-SNMP的源代码 选择一个SNMP版本,比如5.7.1,下载地址如下:http://sourceforge.net/projects/net-snmp/files ...
- 利用/proc/pid/pagemap将虚拟地址转换为物理地址
内核文档: Documentation/vm/pagemap.txt pagemap is a new (as of 2.6.25) set of interfaces in the kernel t ...
- Java 下载文件
public @ResponseBody void exportExcel(HttpServletRequest request, HttpServletResponse response, Khxx ...