有这么一个情况:有一个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是专门用来设置读写优先级的,但是我用完之后无效。怪哉,我哪用错了?

Linux下pthread的读写锁的优先级问题相关推荐

  1. linux库函数pthread.h------pthread_rwlock_t读写锁说明

    读写锁 索引: 初始化一个读写锁pthread_rwlock_init 读锁定读写锁 pthread_rwlock_rdlock 非阻塞读锁定 pthread_rwlock_tryrdlock 写锁定 ...

  2. linux 进程 读写锁,linux 下实现高性能读写锁(read/write lock)

    前一篇文章分析了Windows slim read/write lock的工作原理.我们知道它的设计相当精妙,于是我们可以借鉴它的思路来设计linux下的读写锁. 在这个读写锁的设计上,需要注意的是l ...

  3. Linux多线程的同步------读写锁

    前面介绍过Linux多线程同步的另外两个方法------互斥锁和信号量 Linux多线程的同步-----信号量和互斥锁_神厨小福贵!的博客-CSDN博客 下面来看一下读写锁: 读写锁和互斥锁都带有一个 ...

  4. linux下使用fread读socket套接字的注意点

    linux下使用fread读socket套接字的注意点 linux总所周知,一切皆文件.因此我们在读写文件时觉得fread,recv这些可以随便用.下面看看有哪些注意事项呢. 因为C库的文件处理函数较 ...

  5. 【Linux内核】RW读写锁机制

    读写锁机制 Linux内核中读写锁的机制是一种多读单写的锁机制,它允许多个读操作同时进行,但只能有一个写操作进行.当有写操作时,所有读操作都会被阻塞,直到写操作完成. 在内核中,读写锁主要由以下两个结 ...

  6. linux进阶51——pthread_rwlock_t(读写锁)

    1. 概念 读写锁与互斥量类似.但是互斥量要么是锁住状态,要么就是不加锁状态,而且一次只有一个线程可以对其加锁 不过读写锁允许更高的并行性,而且有更多的状态 读写锁可以有3种状态: ①读模式下加锁 ② ...

  7. linux线程同步(3)-读写锁

    一.概述                                                    读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区, ...

  8. linux flash擦除命令,Linux下flash操作读、写、擦除步骤

    描述 1. 背景介绍 在板上,ZYNQ PL部分通过EMC连接一片NOR FLASH,地址空间如下: 可以看到NOR FLASH的起始地址为0x80000000,这是物理地址,可以把数据存放在以该地址 ...

  9. Linux下有关可读可写可执行权限rwx:.sh:权限不够

    在某天之前,我运行Linux下的.sh文件,都是采用./xxx.sh的方式. 突然有一天,我发现这个方式运行不了了...提示我 然后,我才知道,原来文件夹还是有权限的... 所以,请教了一下公司大神, ...

最新文章

  1. 软件开发向大数据开发过渡_如果您是过渡到数据科学的开发人员,那么这里是您的最佳资源...
  2. ExcelReport第三篇:扩展元素格式化器
  3. day10 局部变量 全局变量 作用域前奏
  4. Linux下KVM虚拟机基本管理及常用命令(转)
  5. mysql+distinct+max_MySQL中distinct与group by之间的性能进行比较
  6. 小程序 | 微信小程序from报名表单提交至数据库(含js提交函数)
  7. sftp api java_SFTP例子2----使用JSch实现SFTP文件传输
  8. ci php redis,一次基于CI的Redis性能问题定位
  9. Matlab系列教程_基础知识_绘图(二)
  10. java菜鸟教程100_JAVA/JSP学习系列之一
  11. 数控技术 - 直线插补 - 数字积分法(DDA)
  12. Visual Studio Code (vscode)配置LaTeX最详细版(vscode下载安装+基本设置+内外pdf查看器设置+个人配置代码)
  13. 超级账本基金会执行董事Daniela Barbosa:开源区块链已成主流
  14. php采集今日头条出现问题,使用php蓝天采集抓取今日头条ajax的文章内容
  15. Redis学习之srem命令
  16. 在嵌入式linux上玩OpenGL
  17. 动态站点:部署论坛系统Discuz!
  18. 让小伙伴大呼过瘾的数据可视化作品!
  19. 生成镶嵌数据集涉及的一些概念和工具
  20. 2021 RoboCom 世界机器人开发者大赛-本科组(决赛)7-4猛犸不上 Ban(最短路)

热门文章

  1. Linux screen命令与后台执行任何程序
  2. 华为Android10版怎么截屏,安卓手机截图方法 华为手机如何截图 - 云骑士一键重装系统...
  3. spring的定时任务schedule
  4. 博客园 文章和随笔区别
  5. [mount]linux 挂载时 mount: wrong fs type, bad option, bad superblock on /dev/sdb
  6. signalr中Group 分组群发消息的简单使用
  7. 翻译:重载解决和Null
  8. python语言分数等级转化_如何把分数转化成等级
  9. VxWorks任务调度
  10. (96)自动售货机状态转移图,面试必问(二十)(第20天)