多线程读写数据方法之读写锁方法与shared_ptr+互斥锁方法的比较

本文对比了两种多线程下读写共享资源的方法:读写锁和使用shared_ptr结合互斥锁。读写锁在读写时分别加锁。而shared_ptr+互斥锁方法中,读操作通过加锁增加引用计数,写操作可能涉及新对象的创建和交换。这种方法允许读操作在写操作进行时继续,但写时可能有数据拷贝。实验表明,该方法在某些情况下能缩短整体操作时间。
摘要由CSDN通过智能技术生成

对共享资源进行多线程读写操作有很多方法,本文举出两种方法并进行对比。

一:读写锁方法。线程进行读操作时以读的方式加锁,线程进行写操作时用写的方式加锁。

二:另外一种比较新奇的方法是使用shared_ptr+互斥锁。shared_ptr是一种用引用计数实现的智能指针,当计数为零时,它接管的对象会被销毁。利用这一点可以与互斥锁配合使用实现另外一种比读写锁更为高效的方法。方法如下:

1:对于read端,在读之前加互斥锁,把引用计数加1,解除互斥锁(临界区非常小),读完之后计数减1,这样保证在读期间其引用计数大于1,可以防止并发写。

2:对于write端,对整个写函数加互斥锁,如果引用计数为1,这时可以安全修改共享对象,不必担心有人读它;当引用计数大于1时,生成一个新的数据对象(旧对象的深拷贝),并用一个shared_ptr进行保管,然后与原来的shared_ptr进行交换,对新对象进行写操作。这时旧对象只被读函数中的shared_ptr保管,当那些函数都运行完毕时,旧对象的引用计数成为零,就对象被自动销毁。

这种方法的好处就是在读的时候可以去写,从而会使操作时间有所缩短,缺点是写时有可能会拷贝旧数据,这点到不必太多担心。下面的程序验证了写时拷贝数据发生的概率在1%左右,而且整体时间也会比读写锁方法有所缩短。

实验模拟了股票的购买和查询过程,实验采用四线程,两个线程买股票(写),两个线程查询股票(读)。


CustomerData.h。shared_ptr+互斥锁方法

#ifndef CUSTOMERDATA_H_INCLUDED
#define CUSTOMERDATA_H_INCLUDED

#include"MutexLock.h"
#include"MutexLockGuard.h"
#include<boost/shared_ptr.hpp>
#include<boost/noncopyable.hpp>
#include<vector>
#include<map>
#include<iostream>
using namespace std;

typedef struct MyStock{
    string stockName;
    int itemCnt;
}MyStock;

class CustomerData{
private:
    typedef vector<MyStock> StockList;
    typedef boost::shared_ptr<StockList> Stoptr;
    typedef map<string,StockList> Map;
    typedef boost::shared_ptr<Map> Maptr;
    Maptr data_;
    MutexLock mutex_;
    static int CopyTime;
    static int WriteTime;
    public:
    CustomerData():data_(new Map){}
    void traverse(){
        Maptr tmp;
        {
            MutexLockGuard lock(mutex_);
            tmp=data_;
            cout<<"Copy Time="<<CopyTime<<endl;
            cout<<"Write Time="<<WriteTime<<endl;
            cout<<(double)CopyTime*100/WriteTime<<"%"<<endl;
        }
        for(Map::iterator p=data_->begin();p!=data_->end();++p){
            cout<<"-----------------------------"<<endl;
            cout<<"Customer:"<<p->first<<endl;
            for(StockList::iterator q=p->second.begin();q!=p->second.end();++q)
                cout<<"\t"<<q->stockName<<":"<<q->itemCnt<<endl;
            cout<<"-----------------------------"<<endl;
        }
    }

    int queryCnt(const string& customer,const string& stock){
        Maptr tmp;
        {
            MutexLockGuard lock(mutex_);
            tmp=data_;
        }
        Map::iterator p=tmp->find(cust
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值