打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux下pthread的读写锁的优先级问题

有这么一个情况:有一个C实现的HashMap,需要在多个线程之间共享。对它的读操作远远大于写操作。所以采用了pthread的读写锁来保障并发读写时的一致性。

现在测试发现的问题是:因为读操作太多,导致写操作一直拿不到锁。按理说不应该啊,假如有三个线程,线程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 <iostream>
#include <pthread.h>
#include <stdio.h>
#include <assert.h>
 
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 "<<threadCount<<std::endl;
 
  if(pthread_rwlock_rdlock(&rwlock)!=0)
    return NULL;
  std::cout<<"thread1 got the read lock "<<std::endl;
  {int rc=pthread_barrier_wait(&barr);
    if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
      printf("Could not wait on barrier\n");
    }}
 
  std::cout<<"thread "<<threadCount<<" work done"<<std::endl;
 
  int rc=pthread_barrier_wait(&barr2);
  if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
      printf("Could not wait on barrier\n");
  }
 
  std::cout<<"thread "<<threadCount<<" return"<<std::endl;
}
 
 
void * thr2_entry(void *arg){
  int threadCount=*(int*)arg;
  std::cout<<"this is thread "<<threadCount<<std::endl;
  if(threadCount!=1){int rc=pthread_barrier_wait(&barr);
  if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
      printf("Could not wait on barrier\n");
  }}
 
  if(threadCount==1){
    if(pthread_rwlock_rdlock(&rwlock)!=0)
      return NULL;
    std::cout<<"thread1 got the read lock "<<std::endl;
    {int rc=pthread_barrier_wait(&barr);
      if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
    printf("Could not wait on barrier\n");
      }}
 
  } 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"<<std::endl;
      pthread_rwlock_unlock(&rwlock);
      std::cout<<"thread3 released lock"<<std::endl;
    }
  }
  std::cout<<"thread "<<threadCount<<" work done"<<std::endl;
 
  int rc=pthread_barrier_wait(&barr2);
  if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
      printf("Could not wait on barrier\n");
  }
 
  std::cout<<"thread "<<threadCount<<" return"<<std::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\n");
      return -1;
    }
 
  if(pthread_barrier_init(&barr2, NULL, 3)) {
      printf("Could not create a barrier\n");
      return -1;
    }
  pthread_rwlockattr_t attr;
  if(pthread_rwlockattr_init(&attr)){
    printf("Could not create a rwlock attr\n");
    return -1;
  }
  // int perf=-1;
 //pthread_rwlockattr_getkind_np(&attr,&perf);  
  //  std::cout<<perf<<std::endl;
  pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NP);
  if(pthread_rwlock_init(&rwlock,&attr)){
    printf("Could not create a rwlock\n");
    return -1;
  }
  int threadCount[]={1,2,3};
  if(pthread_create(&thr1, NULL, &thr1_entry, (void*)&threadCount[0])) {
      printf("Could not create thread %d\n", threadCount);
      return -1;
    }
 
  if(pthread_create(&thr2, NULL, &thr2_entry, (void*)&threadCount[1])) {
      printf("Could not create thread %d\n", threadCount);
      return -1;
    }
 
  if(pthread_create(&thr3, NULL, &thr2_entry, (void*)&threadCount[2])) {
      printf("Could not create thread %d\n", 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是专门用来设置读写优先级的,但是我用完之后无效。怪哉,我哪用错了?

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
linux下多线程扑克游戏框架
Linux 多线程和锁
pthread的各种同步机制
[转]linux-多线程
linux c 线程间同步(通信)的几种方法
进程通信之读写锁
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服