Chinaunix首页 | 论坛 | 博客
  • 博客访问: 584616
  • 博文数量: 104
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1559
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-21 00:58
个人简介

锻炼精神,首先要锻炼肉体

文章分类

全部博文(104)

文章存档

2018年(1)

2016年(1)

2015年(101)

2014年(1)

我的朋友

分类: C/C++

2015-02-23 16:48:26

#include

int pthread_mutex_lock( pthread_mutex_t *mutex ) ;
这个方法是用来锁定互斥量,如果该互斥量变量已经被其他的线程锁定,
那么当前调用该方法的线程将会陷入阻塞状态直到互斥量被解锁

int pthread_mutex_trylock ( pthread_mutex_t *mutex ) ;
如果当前系统资源有限,线程长期阻塞会消耗系统中的资源,此方法就是为了防止
线程因长期得不到互斥量而陷入阻塞而设计出的,是当前执行该方法的线程试探性的
获取互斥量,如果获取不到这立即返回而不陷入阻塞,而是返回 EBUSY 的变量用来
表示当前的互斥量被其他的线程占用

int pthread_mutex_unlock ( pthread_mutex_t *mutex ) ;
该方法用于将锁定的互斥量进行解锁


下面的代码是通过互斥量来保护数据结构对象 , 使用到的方法有:
1. int pthread_mutex_lock( pthread_mutex_t *mutex ) ;
2. int pthread_mutex_unlock ( pthread_mutex_t *mutex ) ;

点击(此处)折叠或打开

  1. #include <stdlib.h>
  2. #include <pthread.h>

  3. struct foo
  4. {
  5.     int f_count ;
  6.     pthread_mutex_t f_lock ;
  7.     int f_id ;
  8. } ; // 定义结构体,将互斥量与互斥量保护的变量通过结构体的方式进行关联

  9. /**
  10. foo_alloc 方法是用来根据传入的 id 数值创建 foo 结构体变量,
  11. 为其分配空间,并且进行简单的初始化,最后将指向该创建好的 foo 变量对象
  12. 以返回值的方式进行返回
  13. struct foo 变量中有一个互斥量的变量字段 -- f_lock 
  14. 在 foo_alloc 方法中 连通 struct foo 变量都是通过 malloc 方法从堆空间
  15. 中动态划分的空间,所以该 f_lock 字段是需要通过 pthread_mutex_init 
  16. 这一动态初始化 pthread_mutex_t 变量的方法来初始化,而不是使用宏变量
  17. PTHREAD_MUTEX_INITIALIZER 
  18. */
  19. struct foo *
  20.     foo_alloc ( int id ) /* allocate the object */
  21.     {
  22.         struct foo *fp ;
  23.         if ( ( fp = malloc ( sizeof ( struct foo ) ) ) != NULL )
  24.         {
  25.             fp->f_count = 1 ;
  26.             fp->f_id = id ;
  27.             if ( pthread_mutex_init ( &fp->f_lock , NULL ) != 0 )
  28.             {
  29.                 free ( fp ) ;
  30.                 return (NULL) ;
  31.             }
  32.             
  33.             /* continue initialization */
  34.         }
  35.         return (fp) ;
  36.     }
  37. /**
  38. foo_hold :
  39. 这个方法是通过传入的 struct foo 指针来互斥的对指针所指向的变量中的
  40. f_count 变量进行增加计数操作
  41. 在多个线程都想针对同一个 struct foo 中的 f_count 字段进行增加计数操作的时候,
  42. 只有能够获得互斥锁的线程才能够具有对该变量进行改写的机会,
  43. 其余没有获得互斥锁的线程都会被归入到该互斥锁的阻塞队列中
  44. */
  45. void foo_hold ( struct foo *fp ) /* add a reference to the object */
  46. {
  47.     pthread_mutex_lock ( &fp->f_lock ) ;
  48.     fp->f_count++ ;
  49.     pthread_mutex_unlock (&fp->f_lock ) ;
  50. }

  51. /**
  52. foo_rele : 
  53. 这个方法是对传入指向 struct foo 变量的指针中的 f_count 变量字段进行检查,

  54. 1. 如果该数值在进行自减操作之后等于 1 说明当前线程是最后一个引用该变量的线程,
  55. 最后的使用者负责将加在该 struct foo 变量上面的互斥锁进行解除
  56. 对于互斥量而言,当有互斥量被其他线程引用的时候进行销毁会引发错误
  57. 只有确保没有线程使用该互斥量的时对其销毁并释放空间才可以,
  58. 所以当 --fp->f_count == 0 的时候,说明当前引用的线程为最后一个,在调用
  59. pthread_mutex_unlock 释放最后一个线程对该互斥量的占用之后,可以安全将其销毁 ;

  60. 2.当然,如果 --fp->f_count != 0 则说明,除了当前线程仍然还有其余线程占用或是
  61. 试图占用该互斥锁,销毁线程的操作则是不允许的
  62. */
  63. void foo_rele ( struct foo *fp ) /* release a reference to the object */
  64. {
  65.     pthread_mutex_lock ( &fp->f_lock ) ;
  66.     if ( --fp->f_count == 0 )
  67.     {
  68.         // this is the last reference
  69.         pthread_mutex_unlock ( &fp->f_lock ) ;
  70.         pthread_mutex_destory ( &fp->f_lock ) ;
  71.         free ( fp ) ;
  72.     }
  73.     else
  74.     {
  75.         pthread_mutex_unlock ( &fp->f_lock ) ;
  76.     }
  77. }

在线程 A 与线程 B 运行的时候分别申请两个互斥量 m1 m2,在线程 A 运行的时候申请了互斥量 m1 所保护的资源 x1,
同时还需要申请使用被线程 B 所申请的互斥量 m2 所保护的资源 x2 ;
线程 B 在运行的时候首先申请了互斥量 m2 所保护的资源,同时还需要申请被线程 A 运行的时候申请的互斥量 m1 所保护的资源
x1 , 线程 B  就会陷入互斥量 m1 的阻塞, 而线程 A 也同时陷入了互斥量 m2 的阻塞。 
这就是的死锁,为了防止死锁的发生,通常可以使用 pthread_mutex_trylock 

在线程 A 运行申请互斥量 m1 之后,此时互斥量 m2 也被线程 B 申请占用。
如果线程 A 使用 pthread_mutex_trylock 来申请占用互斥量 m2 的话,则会因为互斥量已经被占用而立即返回
出错提示返回值 : EBUSY, 该宏变量数值来提示互斥量 m2 已经被其他的线程占用。通过这种方法线程就不会进入
到互斥量 m2 的阻塞队列。同理,线程 B 也不会进入到线程 A 占用的互斥量 m1 的阻塞队列,从而放置了死锁 

点击(此处)折叠或打开

  1. #include <stdlib.h>
  2. #include <pthread.h>

  3. struct foo
  4. {
  5.     int f_count ;
  6.     pthread_mutex_t f_lock ;
  7.     int f_id ;
  8. } ;

  9. struct foo * foo_alloc ( int id )
  10. {
  11.     struct foo *fp ;
  12.     if ( ( fp = malloc ( sizeof ( struct foo ) ) ) != NULL )
  13.     {
  14.         fp->f_count = 1 ;
  15.         fp->f_id = id ;
  16.         
  17.         if ( pthread_mutex_init ( &fp->f_lock , NULL ) != 0 )
  18.         {
  19.             free ( fp ) ;
  20.             return ( NULL ) ;
  21.         }
  22.     }
  23.     
  24.     return fp ;
  25. }

  26. void foo_try_hold ( struct foo *fp )  // 与上述方法所不同的是,在多个线程共同争夺同一个互斥锁变量的时候,没有获得
  27.                                       // 到互斥锁的线程并不会陷入到该互斥锁的阻塞队列中,而是立即返回 ,这就是 trylock 与lock 的不同
  28. {
  29.      // try to get the mutex , if can not get means someone else
  30.      // are occupying the mutex
  31.      if ( pthread_mutex_trylock ( &fp->f_lock ) != 0 )
  32.      {
  33.         printf ( "failed to get mutex \n " ) ;
  34.         return ;
  35.      }
  36.      else
  37.      {
  38.          fp->f_count++ ;
  39.          pthread_mutex_unlock ( &fp->f_lock ) ;
  40.      }
  41. }

  42. void foo_rele ( struct foo *fp )
  43. {
  44.      if ( pthread_mutex_trylock ( &fp->f_lock ) != 0 )
  45.      {
  46.         pritnf ( "failed to get mutex lock \n" ) ;
  47.         return ;
  48.      }
  49.      else
  50.      {
  51.         if ( --fp->f_count == 0 )
  52.         {
  53.             // this is the last reference
  54.             pthread_mutex_unlock ( &fp->f_lock ) ;
  55.             pthread_mutex_destory ( &fp->f_lock ) ;
  56.         }
  57.         else
  58.         {
  59.             pthread_mutex_unlock ( &fp->f_lock ) ;
  60.         }
  61.      }
  62. }
end
阅读(1055) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~