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

长平狐 发布于 2012/09/03 12:56
阅读 854
收藏 0

 在上一篇文章中,讲述了线程中互斥锁的使用,达到对共享资源互斥使用。除了使用互斥锁,信号量,也就是操作系统中所提到的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、函数实现。

view plaincopy to clipboardprint?
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <semaphore.h> 
#include <errno.h> 
 
#define return_if_fail(p)  /  
        if(!p){printf ("[%s]: func error!", __func__);return;}  
 
typedef struct _PrivInfo  
{  
  sem_t    sem;  
  int      lock_var;  
  time_t   end_time;  
}PrivInfo;  
 
static void info_init (PrivInfo* thiz);  
static void pthread_func_1 (PrivInfo* thiz);  
static void pthread_func_2 (PrivInfo* thiz);  
 
int main (int argc, char** argv)  
{  
  pthread_t pt_1 = 0;  
  pthread_t pt_2 = 0;  
  int ret = 0;  
  PrivInfo* thiz = NULL;  
 
  thiz = (PrivInfo* )malloc (sizeof (PrivInfo));  
  if (thiz == NULL)  
  {  
    printf ("[%s]:Failed to malloc PrivInfo./n");  
    reutrn -1;  
  }  
 
  info_init (thiz);  
    
  ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, NULL);  
  if (net != 0)  
  {  
    perror ("pthread_1_create:");  
  }  
 
  ret = pthread_create (&pt_1, NULL, (void*)pthread_func_2, NULL);  
  if (ret != 0)  
  {  
    perror ("pthread_2_create:");  
  }  
 
  pthread_join (pt_1, NULL);  
  pthread_join (pt_2, NULL);  
 
  sem_destroy (thiz->sem);  
  free (thiz);  
  thiz = NULL;  
 
  return;  
}  
 
static void info_init (PrivInfo* thiz)  
{  
   return_if_fail (thiz != NULL);  
 
   thiz->lock_var = 0;  
   thiz->end_time = time(NULL) + 10;  
 
   sem_init (&thiz->sem, 0,  1);  
 
   return;  
}  
 
static void pthread_func_1 (PrivInfo* thiz)  
{  
  int i = 0;  
 
  while (time(NULL) < thiz->end)  
  {  
     sem_wait (&thiz->sem);  
     printf ("pthread: pthread1 get lock./n");  
 
     for (i = 0; i < 2; i ++)  
     {  
         thiz->lock_var ++;  
         sleep (1);  
     }  
 
     sem_post (&thiz->sem);  
     printf ("pthread1: pthread1 unlock/n");  
 
     sleep (1);  
  }  
 
   return;  
}  
 
static void pthread_func_2 (PrivInfo* thiz)  
{  
   return_if_fail (thiz != NULL);  
 
   while (time (NULL) < thiz->end_time)  
   {  
      sem_wait (&thiz->sem);  
      printf ("pthread2: pthread2 get lock!/n");  
      printf ("the lock_var = %d/n", thiz->lock_var);  
 
      sem_post (&thiz->sem);  
      printf ("phtread2: pthread2 unlock./n");  
 
      sleep (3);  
   }  
 
   return;  

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>

#define return_if_fail(p)  /
        if(!p){printf ("[%s]: func error!", __func__);return;}

typedef struct _PrivInfo
{
  sem_t    sem;
  int      lock_var;
  time_t   end_time;
}PrivInfo;

static void info_init (PrivInfo* thiz);
static void pthread_func_1 (PrivInfo* thiz);
static void pthread_func_2 (PrivInfo* thiz);

int main (int argc, char** argv)
{
  pthread_t pt_1 = 0;
  pthread_t pt_2 = 0;
  int ret = 0;
  PrivInfo* thiz = NULL;

  thiz = (PrivInfo* )malloc (sizeof (PrivInfo));
  if (thiz == NULL)
  {
    printf ("[%s]:Failed to malloc PrivInfo./n");
    reutrn -1;
  }

  info_init (thiz);
 
  ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, NULL);
  if (net != 0)
  {
    perror ("pthread_1_create:");
  }

  ret = pthread_create (&pt_1, NULL, (void*)pthread_func_2, NULL);
  if (ret != 0)
  {
    perror ("pthread_2_create:");
  }

  pthread_join (pt_1, NULL);
  pthread_join (pt_2, NULL);

  sem_destroy (thiz->sem);
  free (thiz);
  thiz = NULL;

  return;
}

static void info_init (PrivInfo* thiz)
{
   return_if_fail (thiz != NULL);

   thiz->lock_var = 0;
   thiz->end_time = time(NULL) + 10;

   sem_init (&thiz->sem, 0,  1);

   return;
}

static void pthread_func_1 (PrivInfo* thiz)
{
  int i = 0;

  while (time(NULL) < thiz->end)
  {
     sem_wait (&thiz->sem);
     printf ("pthread: pthread1 get lock./n");

     for (i = 0; i < 2; i ++)
     {
         thiz->lock_var ++;
         sleep (1);
     }

     sem_post (&thiz->sem);
     printf ("pthread1: pthread1 unlock/n");

     sleep (1);
  }

   return;
}

static void pthread_func_2 (PrivInfo* thiz)
{
   return_if_fail (thiz != NULL);

   while (time (NULL) < thiz->end_time)
   {
      sem_wait (&thiz->sem);
      printf ("pthread2: pthread2 get lock!/n");
      printf ("the lock_var = %d/n", thiz->lock_var);

      sem_post (&thiz->sem);
      printf ("phtread2: pthread2 unlock./n");

      sleep (3);
   }

   return;
}

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

~~END~~


原文链接:http://blog.csdn.net/hanchaoman/article/details/4798653
加载中
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部