Chinaunix首页 | 论坛 | 博客
  • 博客访问: 53282
  • 博文数量: 8
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 75
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-11 20:04
文章分类
文章存档

2017年(2)

2016年(3)

2014年(2)

2013年(1)

我的朋友

分类: C/C++

2014-10-15 19:37:25

    今天一程序由于读写锁的问题,导致程序一线程死掉。查完了所有的代码,发现加锁之后,均有释放的地方。后来,推测出最有可能的情况:多个线程去读,在写线程加锁时,至少有一个线程没有释放,而后续的读线程继续加锁,导致该写线程饿死。
    于是写了以下代码进行测试:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <time.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <strings.h>

  7. pthread_rwlock_t link;

  8. void * t_hand()
  9. {


  10.         int i = 0;
  11.         while(1)
  12.         {
  13.                 printf("++++++++++++++++++++++++++\n");
  14.                 pthread_rwlock_rdlock(&link);
  15.                 printf("---------------------------\n");
  16.                 pthread_rwlock_unlock(&link);
  17.                 printf("=========================== i = %d \n",i++);
  18.                 sleep(1);
  19.                 if( i == 7)
  20.                     break;

  21.         }

  22.         pthread_rwlock_unlock(&link);

  23. }




  24. int main(int argc, char ** argv)
  25. {
  26.     int ret = 0;
  27.     printf(" EBUSY = %d, EINVAL = %d, EAGAIN = %d, EDEADLK = %d\n", EBUSY, EINVAL, EAGAIN, EDEADLK);

  28.     pthread_rwlock_init(&link,NULL);


  29.     pthread_t pid ;

  30.     pthread_rwlock_rdlock(&link);

  31.     pthread_create(&pid,NULL,t_hand,NULL);

  32.     sleep(1);

  33.     printf("before wrlock\n");
  34.     pthread_rwlock_wrlock(&link);
  35.     printf("after wrlock\n");

  36.     sleep(100);

  37. }

最后发现输出是以下内容:

点击(此处)折叠或打开

  1. EBUSY = 16, EINVAL = 22, EAGAIN = 11, EDEADLK = 35
  2. ++++++++++++++++++++++++++
  3. ---------------------------
  4. =========================== i = 0
  5. before wrlock
  6. ++++++++++++++++++++++++++
  7. ---------------------------
  8. =========================== i = 1
  9. ++++++++++++++++++++++++++
  10. ---------------------------
  11. =========================== i = 2
  12. ++++++++++++++++++++++++++
  13. ---------------------------
  14. =========================== i = 3
  15. ++++++++++++++++++++++++++
  16. ---------------------------
  17. =========================== i = 4
  18. ++++++++++++++++++++++++++
  19. ---------------------------
  20. =========================== i = 5
  21. ++++++++++++++++++++++++++
  22. ---------------------------
  23. =========================== i = 6
  24. after wrlock
从输出上不难看出,在有一把读锁加上之后,再加上写锁,而后续再有读锁加上时,写锁将一直处于阻塞状态,直到所有的读锁都释放掉。而写锁要加上的条件就是:当前没有读锁。

在将代码修改后:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <time.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <strings.h>



  7. pthread_rwlock_t link;


  8. void * t_hand()
  9. {


  10.         int i = 0;
  11.         while(1)
  12.         {
  13.                 printf("++++++++++++++++++++++++++\n");
  14.                 pthread_rwlock_rdlock(&link);
  15.                 printf("---------------------------\n");
  16.                 pthread_rwlock_unlock(&link);
  17.                 printf("=========================== i = %d \n",i++);
  18.                 sleep(1);
  19.                 if( i == 7)
  20.                     break;

  21.         }

  22.         pthread_rwlock_unlock(&link);

  23. }




  24. int main(int argc, char ** argv)
  25. {
  26.     int ret = 0;
  27.     printf(" EBUSY = %d, EINVAL = %d, EAGAIN = %d, EDEADLK = %d\n", EBUSY, EINVAL, EAGAIN, EDEADLK);

  28.     //pthread_rwlock_init(&link,NULL);

  29.     pthread_rwlockattr_t attr;
  30.     pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
  31.     pthread_rwlock_init(&link,&attr);

  32.     pthread_t pid ;

  33.     pthread_rwlock_rdlock(&link);

  34.     pthread_create(&pid,NULL,t_hand,NULL);

  35.     sleep(1);

  36.     printf("before wrlock\n");
  37.     pthread_rwlock_wrlock(&link);
  38.     printf("after wrlock\n");

  39.     sleep(100);

  40. }
输出以下内容:


点击(此处)折叠或打开

  1. EBUSY = 16, EINVAL = 22, EAGAIN = 11, EDEADLK = 35
  2. ++++++++++++++++++++++++++
  3. ---------------------------
  4. =========================== i = 0
  5. before wrlock
  6. ++++++++++++++++++++++++++

然后一直处于等待状态(此时,已经死锁)。

从上不难看出,一直使用的默认属性对于读写锁的处理方式是:有写不能能,有读不能写但是可读。该策略容易对一些读频繁,写较少的程序造成写线程饿死。

阅读(3274) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~