使用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