本例子是模拟的读者写者问题,采用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缩小临界区的例子的更多相关文章

  1. mysql索引设计的注意事项(大量示例,收藏再看)

    mysql索引设计的注意事项(大量示例,收藏再看) 目录 一.索引的重要性 二.执行计划上的重要关注点 (1).全表扫描,检索行数 (2).key,using index(覆盖索引) (3).通过ke ...

  2. 再看Ajax

    再回顾Ajax相关的内容,再次梳理学习还是很有必要的,尤其是实际的开发中,ajax更是必不可少,仔细学习以便避免不必要的错误. 文章导读: --1.使用XMLHttpRequest---------- ...

  3. 再看ftp上传文件

    前言 去年在项目中用到ftp上传文件,用FtpWebRequest和FtpWebResponse封装一个帮助类,这个在网上能找到很多,前台使用Uploadify控件,然后在服务器上搭建Ftp服务器,在 ...

  4. 再看 AspriseOCR - OCR应用开发 -20151124

    再看 AspriseOCR - OCR应用开发 我写这个博文时间为 2015/11/24日,注意时间因为,网上很多文章时间上很久远,有的已经不能参考了 很多人面对从图片中识别文字或者数字0~9  A~ ...

  5. Android菜鸟的成长笔记(17)—— 再看Android中的Unbounded Service

    原文:Android菜鸟的成长笔记(17)-- 再看Android中的Unbounded Service 前面已经写过关于startService(Unbounded Service)的一篇文章:&l ...

  6. 再看case语句

    再看case语句,case语句只处理单条记录,而不是set 列名的使用,可以当做数值来使用: case when 后面简直是完美的的,什么东西都是能放的,只要是一个逻辑上的true/false的逻辑就 ...

  7. android 智能指针的学习先看邓凡平的书扫盲 再看前面两片博客提升

    android 智能指针的学习先看邓凡平的书扫盲 再看前面两片博客提升

  8. python基础----再看property、描述符(__get__,__set__,__delete__)

    一.再看property                                                                          一个静态属性property ...

  9. perf使用的问题,再看perf record,perf record 设置的采样频率,采样频率是如何体现在

    当perf stat -e branches 是统计 再看perf record,perf record是为了是记录时间发生的时候的调用栈, 在我的测试代码中总共有200,000,000条branch ...

随机推荐

  1. JMS Java消息服务(Java Message Service)

    JMS 在一些场景下RPC的同步方式可能不太适合业务逻辑的处理,并且这种方式在某些场景下会导致业务的紧耦合. 基于异步交互模型的JMS解决了RPC产生的紧耦合问题,它提供了一个可以通过网络访问的抽象消 ...

  2. python中关于if-else使用性能的一点感悟

    今天做leetcode第7题关于数字倒序的问题,分别使用如下程序:(72ms) class Solution: def reverse(self, x): """ :ty ...

  3. Codeforces Round #272 (Div. 2) E. Dreamoon and Strings 动态规划

    E. Dreamoon and Strings 题目连接: http://www.codeforces.com/contest/476/problem/E Description Dreamoon h ...

  4. shell脚本调用C语言之字符串切分函数——strtok

    今天上午在写一个需求,要求的比较急,要求当天完成,我大致分析了一下,可以采用从shell脚本中插入一连串的日期,通过调用proc生成的可执行文件,将日期传入后台数据库,在数据库中进行计算.需要切分日期 ...

  5. 三星打印机SCX-4824HN全套驱动(打印/扫描)

    链接: https://pan.baidu.com/s/1EUXsti4niHlYcMHMJqqnXA 密码: r91a

  6. 实现DIV层内的文字垂直居中(转)

    有时候,为了网页设计的美观,需要把div+css设计的页面里的某些div层里的文字垂直居中,包括多行文字以及单行文字:方法有不少,但真正能实现而代码又简洁的介绍不多,flymorn就为大家介绍几种适用 ...

  7. Eclipse配置开发Go的插件——Goclipse

    引言: 上篇 <Golang快速入门(不用急,但要快)> 我们大致过了一遍Go语言的基本语法,但在开始正式的项目创建前,有必要选择一个比较顺手的 IDE (编辑器),由于之前一直都是做Ja ...

  8. asp.net MVC 中 Session统一验证的方法

    验证登录状态的方法有:1  进程外Session   2 方法过滤器(建一个类继承ActionFilterAttribute)然后给需要验证的方法或控制器加特性标签 3 :新建一个BaseContro ...

  9. Java嵌入式数据库H2学习总结(一)——H2数据库入门

    一.H2数据库介绍 常用的开源数据库有:H2,Derby,HSQLDB,MySQL,PostgreSQL.其中H2和HSQLDB类似,十分适合作为嵌入式数据库使用,而其它的数据库大部分都需要安装独立的 ...

  10. 利用阿里云提供的镜像快速更换本地的yum源

    打开网页:http://mirrors.aliyun.com/ 从“ 文件列表 ”找到自己的系统: Mirror Last update Help CPAN 2015-07-15 15:36:50   ...