zoukankan      html  css  js  c++  java
  • 再看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 

  • 相关阅读:
    mysql 主从架构搭建
    tomcat+nginx 反向代理 动静分离
    ELK(Elasticsearch + Logstash + Kibana)安装部署对nginx的日志收集
    Kibana server is not ready yet出现的原因
    apache+tomcat+单机双实例+动静分离+负载均衡
    docker的基本安装和简单使用+Dockerfile常用指令
    LVS+keepalived+DR 负载均衡高可用
    md5sum摘要
    python爬虫
    python和数据库
  • 原文地址:https://www.cnblogs.com/pangblog/p/3402525.html
Copyright © 2011-2022 走看看