Linux下pthreadの読み書きロックの優先度の問題
15011 ワード
1つのC実装のHashMapがあり,複数のスレッド間で共有する必要がある.読み取り操作は書き込み操作よりはるかに大きい.従ってpthreadの読み書きロックを採用し,同時読み書き時の一貫性を保障した.
今テストで発見された問題は、読み取り操作が多すぎて、書き込み操作がロックされていないことです.当然ではありませんが、もし3つのスレッドがあれば、スレッド1はまずリードロックを申請して成功して手に入れて、それからスレッド2はライトロックを申請して必然的に待機して、それからスレッド3はリードロックを申請して、それでは待機に陥るべきです.pthread_rwlock_rdlockのman pagesでは「The calling thread acquires the read lock if a writer does not hold the lock and there are no writers blocked on the lock」と言っていますが、実際に私のテストの結果はスレッド3がリードロックを手に入れたことです.
このシーンをシミュレートするために、しばらく考えていました.スレッド2が待機状態に陥っているとどうやって判断しますか?その後私のテストはこうしました
スレッド1スレッド2スレッド3
rdlock
barrier barrier barrier
wrlock while(true) {rdlock;unlock;}
コードは次のとおりです.
今テストで発見された問題は、読み取り操作が多すぎて、書き込み操作がロックされていないことです.当然ではありませんが、もし3つのスレッドがあれば、スレッド1はまずリードロックを申請して成功して手に入れて、それからスレッド2はライトロックを申請して必然的に待機して、それからスレッド3はリードロックを申請して、それでは待機に陥るべきです.pthread_rwlock_rdlockのman pagesでは「The calling thread acquires the read lock if a writer does not hold the lock and there are no writers blocked on the lock」と言っていますが、実際に私のテストの結果はスレッド3がリードロックを手に入れたことです.
このシーンをシミュレートするために、しばらく考えていました.スレッド2が待機状態に陥っているとどうやって判断しますか?その後私のテストはこうしました
スレッド1スレッド2スレッド3
rdlock
barrier barrier barrier
wrlock while(true) {rdlock;unlock;}
コードは次のとおりです.
#include
#include
#include
#include
static pthread_barrier_t barr;
static pthread_barrier_t barr2;
static pthread_rwlock_t rwlock;
void * thr1_entry(void *arg){
int threadCount=*(int*)arg;
std::cout<<"this is thread "<
if(pthread_rwlock_rdlock(&rwlock)!=0)
return NULL;
std::cout<<"thread1 got the read lock "<<:endl>
{int rc=pthread_barrier_wait(&barr);
if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("Could not wait on barrier
");
}}
std::cout<<"thread "<" work done"<<:endl>
int rc=pthread_barrier_wait(&barr2);
if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("Could not wait on barrier
");
}
std::cout<<"thread "<" return"<<:endl>
}
void * thr2_entry(void *arg){
int threadCount=*(int*)arg;
std::cout<<"this is thread "<
if(threadCount!=1){int rc=pthread_barrier_wait(&barr);
if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("Could not wait on barrier
");
}}
if(threadCount==1){
if(pthread_rwlock_rdlock(&rwlock)!=0)
return NULL;
std::cout<<"thread1 got the read lock "<<:endl>
{int rc=pthread_barrier_wait(&barr);
if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("Could not wait on barrier
");
}}
} else if(threadCount==2){
pthread_rwlock_wrlock(&rwlock);
} else if(threadCount==3){
while(true){
sleep(5);
pthread_rwlock_rdlock(&rwlock);
std::cout<<"thread3 got lock"<<:endl>
pthread_rwlock_unlock(&rwlock);
std::cout<<"thread3 released lock"<<:endl>
}
}
std::cout<<"thread "<" work done"<<:endl>
int rc=pthread_barrier_wait(&barr2);
if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("Could not wait on barrier
");
}
std::cout<<"thread "<" return"<<:endl>
}
int main(int argc,char* argv[]){
pthread_t thr1,thr2,thr3;
if(pthread_barrier_init(&barr, NULL, 3)) {
printf("Could not create a barrier
");
return -1;
}
if(pthread_barrier_init(&barr2, NULL, 3)) {
printf("Could not create a barrier
");
return -1;
}
pthread_rwlockattr_t attr;
if(pthread_rwlockattr_init(&attr)){
printf("Could not create a rwlock attr
");
return -1;
}
// int perf=-1;
//pthread_rwlockattr_getkind_np(&attr,&perf);
// std::cout<
pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NP);
if(pthread_rwlock_init(&rwlock,&attr)){
printf("Could not create a rwlock
");
return -1;
}
int threadCount[]={1,2,3};
if(pthread_create(&thr1, NULL, &thr1_entry, (void*)&threadCount[0])) {
printf("Could not create thread %d
", threadCount);
return -1;
}
if(pthread_create(&thr2, NULL, &thr2_entry, (void*)&threadCount[1])) {
printf("Could not create thread %d
", threadCount);
return -1;
}
if(pthread_create(&thr3, NULL, &thr2_entry, (void*)&threadCount[2])) {
printf("Could not create thread %d
", threadCount);
return -1;
}
pthread_join(thr1,NULL);
pthread_join(thr2,NULL);
pthread_join(thr3,NULL);
pthread_barrier_destroy(&barr);
pthread_rwlock_destroy(&rwlock);
return 0;
}
システムはFedora 14であり、スレッドライブラリはデフォルトのNPTLである.pthread_rwlockattr_setkind_npは み きの を するために されていますが、 い わった は です.おかしいですね. はどうして っていますか.