新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 多线程编程之:Linux线程编程

多线程编程之:Linux线程编程

作者:时间:2014-10-17来源:网络收藏

  2.信号量线程控制

本文引用地址:http://www.eepw.com.cn/article/264053.htm

  (1)信号量说明。

  在第8章中已经讲到,信号量也就是操作系统中所用到的PV原子操作,它广泛用于进程或线程间的同步与。信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。这里先来简单复习一下PV原子操作的工作原理。

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

  PV原子操作主要用于进程或线程间的同步和这两种典型情况。若用于,几个进程(或线程)往往只设置一个信号量sem,它们的操作流程如图9.2所示。

  当信号量用于同步操作时,往往会设置多个信号量,并安排不同的初始值来实现它们之间的顺序执行,它们的操作流程如图9.3所示。

  

 

  

 

  图9.2 信号量互斥操作 图9.3 信号量同步操作

  (2)函数说明。

  实现了POSIX的无名信号量,主要用于线程间的互斥与同步。这里主要介绍几个常见函数。

  n sem_init()用于创建一个信号量,并初始化它的值。

  n sem_wait()和sem_trywait()都相当于P操作,在信号量大于零时它们都能将信号量的值减一,两者的区别在于若信号量小于零时,sem_wait()将会阻塞进程,而sem_trywait()则会立即返回。

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

  n sem_getvalue()用于得到信号量的值。

  n sem_destroy()用于删除信号量。

  (3)函数格式。

  表9.7列出了sem_init()函数的语法要点。

  表9.8列出了sem_wait()等函数的语法要点。

  (4)使用实例。

  在前面已经通过互斥锁同步机制实现了的顺序执行。下面的例子是用信号量同步机制实现3个线程之间的有序执行,只是执行顺序是跟创建线程的顺序相反。

  /*thread_sem.c*/

  #include

  #include

  #include

  #include

  #define THREAD_NUMBER 3 /* 线程数 */

  #define REPEAT_NUMBER 3 /* 每个线程中的小任务数 */

  #define DELAY_TIME_LEVELS 10.0 /*小任务之间的最大时间间隔*/

  sem_t sem[THREAD_NUMBER];

  void *thrd_func(void *arg)

  {

  int thrd_num = (int)arg;

  int delay_time = 0;

  int count = 0;

  /* 进行P操作 */

  sem_wait(&sem[thrd_num]);

  printf("Thread %d is startingn", thrd_num);

  for (count = 0; count < REPEAT_NUMBER; count++)

  {

  delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;

  sleep(delay_time);

  printf("tThread %d: job %d delay = %dn",

  thrd_num, count, delay_time);

  }

  printf("Thread %d finishedn", thrd_num);

  pthread_exit(NULL);

  }

  int main(void)

  {

  pthread_t thread[THREAD_NUMBER];

  int no = 0, res;

  void * thrd_ret;

  srand(time(NULL));

  for (no = 0; no < THREAD_NUMBER; no++)

  {

  sem_init(&sem[no], 0, 0);

  res = pthread_create(&thread[no], NULL, thrd_func, (void*)no);

  if (res != 0)

  {

  printf("Create thread %d failedn", no);

  exit(res);

  }

  }

  printf("Create treads successn Waiting for threads to finish...n");

  /* 对最后创建的线程的信号量进行V操作 */

  sem_post(&sem[THREAD_NUMBER - 1]);

  for (no = THREAD_NUMBER - 1; no >= 0; no--)

  {

  res = pthread_join(thread[no], &thrd_ret);

  if (!res)

  {

  printf("Thread %d joinedn", no);

  }

  else

  {

  printf("Thread %d join failedn", no);

  }

  /* 进行V操作 */

  sem_post(&sem[(no + THREAD_NUMBER - 1) % THREAD_NUMBER]);

  }

  for (no = 0; no < THREAD_NUMBER; no++)

  {

  /* 删除信号量 */

  sem_destroy(&sem[no]);

  }

  return 0;

  }

  该程序运行结果如下所示:

  $ ./thread_sem

  Create treads success

  Waiting for threads to finish...

  Thread 2 is starting

  Thread 2: job 0 delay = 9

  Thread 2: job 1 delay = 5

  Thread 2: job 2 delay = 10

  Thread 2 finished

  Thread 2 joined

  Thread 1 is starting

  Thread 1: job 0 delay = 7

  Thread 1: job 1 delay = 4

  Thread 1: job 2 delay = 4

  Thread 1 finished

  Thread 1 joined

  Thread 0 is starting

  Thread 0: job 0 delay = 10

  Thread 0: job 1 delay = 8

  Thread 0: job 2 delay = 9

  Thread 0 finished

  Thread 0 joined

linux操作系统文章专题:linux操作系统详解(linux不再难懂)

linux相关文章:linux教程


尘埃粒子计数器相关文章:尘埃粒子计数器原理


关键词: Linux 多线程 互斥

评论


相关推荐

技术专区

关闭