如何优雅的写C++代码 Obotcha介绍(实现读写锁)

使用pthread_rwlock_rdlock()/pthread_rwlock_wrlock()的同学有没有遇到过这种问题:

代码如:

pthread_rwlock_t rwl;
cout << "init: " << pthread_rwlock_init(&rwl, NULL) << endl;

cout << "wrlock: " << pthread_rwlock_wrlock(&rwl) << endl;
cout << "rdlock: " << pthread_rwlock_rdlock(&rwl) << endl;
cout << "unlock: " << pthread_rwlock_unlock(&rwl) << endl;
cout << "unlock: " << pthread_rwlock_unlock(&rwl) << endl;

cout << "wrlock: " << pthread_rwlock_wrlock(&rwl) << endl;    // DEAD!
cout << "unlock: " << pthread_rwlock_unlock(&rwl) << endl;

输出为:
init: 0
wrlock: 0
rdlock: 35
unlock: 0
unlock: 0

按照我的逻辑,

1.如果单一线程持有了写锁,那如果该线程需要获取读锁,那应该允许该线程获。

2.如果单一线程持有了读锁,如果该线程需要再获取写锁,需要等待所有读锁释放以后才能获取.

但是如果目前只有该线程获取读锁,也应该也允许该线程获取写锁。

但是貌似pthread对于读写锁要求比较严格,类似于非recusive mutex.所以在Obotcha里面自己实现了读写锁。

DECLARE_CLASS(ReadWriteLock) {

  public:
    ...

    _ReadWriteLock();

    _ReadWriteLock(String);

    sp<_ReadLock> getReadLock();

    sp<_WriteLock> getWriteLock();

    String getName();

    ~_ReadWriteLock();

  private:
    int mWriteReqCount; 
    //记录申请写锁的线程数,至于这个数目为0,writelock解锁的时候才会唤醒所有的读锁。
    //所以这个读写锁是写有限的。
    
    bool mIsWrite;
    //标记是否有写锁在被占用,如果这个值是true的话,其他线程申请读和写锁就进入等待

    int mWrOwner;
    //记录写锁owner,用处:如果线程A持有了写锁,当他申请读锁的时候我们是允许的。

    int mOwnerCount;
    //记录写锁申请次数,作用:如果一个线程连续申请多个写锁,不会死锁,只会记录数目。
    //只有对应次数的解锁之后才能真正释放。

    std::map<int,int> readOwners;
    //数据内容:<tid,counts>,记录所有的写锁申请的进程id和对应的数目。

    Mutex mMutex;
    Condition mReadCondition;
    Condition mWriteCondition;
}

申请写锁的代码:

int _ReadWriteLock::_writelock(long interval) {
    AutoLock l(mMutex);
    //check whether owner is myself
    int mytid = st(System)::myTid();
    if(mWrOwner == mytid) {
        mOwnerCount++;
        return 0;
    }

    //如果当前没有线程申请写锁,且只有当前线程申请过读锁,默认也能获取到
    if(!mIsWrite) {
        auto iterator = readOwners.find(mytid);
        if(iterator != readOwners.end() && readOwners.size() == 1) {
            mOwnerCount++;
            goto end;
        }
    }
    
    //如果当前其他有线程申请了读锁或者写锁,等~
    mWriteReqCount++;
    while(readOwners.size() != 0 || mIsWrite) {
        int ret = mWriteCondition->wait(mMutex,interval);
        if(ret != 0) {
            mWriteReqCount--;
            return ret;
        }
    }
    mWriteReqCount--;
    mOwnerCount++;
end:
    mIsWrite = true;
    mWrOwner = mytid;
    return 0;
}

详细的实现:

Obotcha/ReadWriteLock.cpp at master · wangsun1983/Obotcha · GitHub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值