linux多线程学习(五)——信号量线程控制


在上一篇文章中,讲述了线程中互斥锁的使用,达到对共享资源互斥使用。除了使用互斥锁,信号量,也就是操作系统中所提到的PV原语,能达到互斥和同步的效果,这就是今天我们所要讲述的信号量线程控制。

PV原语是对整数计数器信号量sem的操作,一次P操作可使sem减一,而一次V操作可是sem加一。进程(或线程)根据信号量的值来判断是否对公共资源具有访问权限。当信号量的值大于零或等于零的时候,该进程(或线程)具有对公共资源访问的权限,否则,当信号量的值小于时,该进程(或线程)就会被阻塞,直到信号量的值大于或等于一。

1、在LINUX中,实现了POSIX的无名信号量,主要用于线程间的互斥同步,下面将简单介绍一些函数接口:

(1)、sem_init

功能:         用于创建一个信号量,并初始化信号量的值。

头文件:       <semaphore.h>

函数原型:     int sem_init (sem_t* sem, int pshared, unsigned int value);

函数传入值:   sem:信号量。

                   pshared:决定信号量能否在几个进程间共享。由于目前LINUX还没有实现进

                               程间共享信息量,所以这个值只能取0。

函数返回值:   0:成功。

                   -1:失败。

(2)其他函数。

int sem_wait       (sem_t* sem);

int sem_trywait   (sem_t* sem);

int sem_post       (sem_t* sem);

int sem_getvalue (sem_t* sem);

int sem_destroy   (sem_t* sem);

功能:sem_wait和sem_trywait相当于P操作,它们都能将信号量的值减一,两者的区别在

        于若信号量的值小于零时,sem_wait将会阻塞进程,而sem_trywait则会立即返回。

        sem_post相当于V操作,它将信号量的值加一,同时发出唤醒的信号给等待的进程

       (或线程)。

        sem_getvalue 得到信号量的值。

        sem_destroy 摧毁信号量。

函数传入值: sem:信号量。

函数返回值: 同上。

2、函数实现。

[c-sharp]  view plain copy
  1. #include <stdio.h>    
  2. #include <stdlib.h>    
  3. #include <unistd.h>    
  4. #include <pthread.h>    
  5. #include <semaphore.h>    
  6. #include <errno.h>    
  7.   
  8. #define return_if_fail(p)  /  
  9.     if((p) == 0){printf ("[%s]: func error!", __func__);return;}    
  10.     
  11. typedef struct _PrivInfo    
  12. {    
  13.   sem_t    sem;    
  14.   int      lock_var;    
  15.   time_t   end_time;    
  16. }PrivInfo;    
  17.     
  18. static void info_init (PrivInfo* thiz);    
  19. static void* pthread_func_1 (PrivInfo* thiz);    
  20. static void* pthread_func_2 (PrivInfo* thiz);    
  21.     
  22. int main (int argc, char** argv)    
  23. {    
  24.   pthread_t pt_1 = 0;    
  25.   pthread_t pt_2 = 0;    
  26.   int ret = 0;    
  27.   PrivInfo* thiz = NULL;    
  28.     
  29.   thiz = (PrivInfo* )malloc (sizeof (PrivInfo));    
  30.   if (thiz == NULL)    
  31.   {    
  32.     printf ("[%s]:Failed to malloc PrivInfo./n");    
  33.     return -1;    
  34.   }    
  35.     
  36.   info_init (thiz);    
  37.       
  38.   ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);    
  39.   if (ret != 0)    
  40.   {    
  41.     perror ("pthread_1_create:");    
  42.   }    
  43.     
  44.   ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);    
  45.   if (ret != 0)    
  46.   {    
  47.     perror ("pthread_2_create:");    
  48.   }    
  49.     
  50.   pthread_join (pt_1, NULL);    
  51.   pthread_join (pt_2, NULL);    
  52.     
  53.   sem_destroy (&thiz->sem);    
  54.   free (thiz);    
  55.   thiz = NULL;    
  56.     
  57.   return;    
  58. }    
  59.     
  60. static void info_init (PrivInfo* thiz)    
  61. {    
  62.    return_if_fail (thiz != NULL);    
  63.     
  64.    thiz->lock_var = 0;    
  65.    thiz->end_time = time(NULL) + 10;    
  66.     
  67.    sem_init (&thiz->sem, 0,  1);    
  68.     
  69.    return;    
  70. }    
  71.     
  72. static void* pthread_func_1 (PrivInfo* thiz)    
  73. {    
  74.   return_if_fail(thiz != NULL);    
  75.     
  76.   int i = 0;    
  77.     
  78.   while (time(NULL) < thiz->end_time)    
  79.   {    
  80.      sem_wait (&thiz->sem);    
  81.      printf ("pthread: pthread1 get lock./n");    
  82.     
  83.      for (i = 0; i < 2; i ++)    
  84.      {    
  85.          thiz->lock_var ++;    
  86.          sleep (1);    
  87.      }    
  88.     
  89.      sem_post (&thiz->sem);    
  90.      printf ("pthread1: pthread1 unlock/n");    
  91.     
  92.      sleep (1);    
  93.   }    
  94.     
  95.    return;    
  96. }    
  97.     
  98. static void* pthread_func_2 (PrivInfo* thiz)    
  99. {    
  100.    return_if_fail (thiz != NULL);    
  101.     
  102.    while (time (NULL) < thiz->end_time)    
  103.    {    
  104.       sem_wait (&thiz->sem);    
  105.       printf ("pthread2: pthread2 get lock!/n");    
  106.       printf ("the lock_var = %d/n", thiz->lock_var);    
  107.     
  108.       sem_post (&thiz->sem);    
  109.       printf ("phtread2: pthread2 unlock./n");    
  110.     
  111.       sleep (3);    
  112.    }    
  113.     
  114.    return;    
  115. }    

从上面的实例中可以看出,通过信号量实现共享资源中的互斥使用,跟上一篇文章中的互斥锁的效果是一样的。但是通过互斥锁还有一个更加方便的功能,就是同步。下一篇文章将讲述线程间通过信号量的同步实现。

 

~~END~~

你可能感兴趣的:(linux多线程学习(五)——信号量线程控制)