在上一篇文章中,讲述了线程中互斥锁的使用,达到对共享资源互斥使用。除了使用互斥锁,信号量,也就是操作系统中所提到的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 plaincopy
  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. #define return_if_fail(p)  /
  8. if((p) == 0){printf ("[%s]: func error!", __func__);return;}
  9. typedef struct _PrivInfo
  10. {
  11. sem_t    sem;
  12. int      lock_var;
  13. time_t   end_time;
  14. }PrivInfo;
  15. static void info_init (PrivInfo* thiz);
  16. static void* pthread_func_1 (PrivInfo* thiz);
  17. static void* pthread_func_2 (PrivInfo* thiz);
  18. int main (int argc, char** argv)
  19. {
  20. pthread_t pt_1 = 0;
  21. pthread_t pt_2 = 0;
  22. int ret = 0;
  23. PrivInfo* thiz = NULL;
  24. thiz = (PrivInfo* )malloc (sizeof (PrivInfo));
  25. if (thiz == NULL)
  26. {
  27. printf ("[%s]:Failed to malloc PrivInfo./n");
  28. return -1;
  29. }
  30. info_init (thiz);
  31. ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);
  32. if (ret != 0)
  33. {
  34. perror ("pthread_1_create:");
  35. }
  36. ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);
  37. if (ret != 0)
  38. {
  39. perror ("pthread_2_create:");
  40. }
  41. pthread_join (pt_1, NULL);
  42. pthread_join (pt_2, NULL);
  43. sem_destroy (&thiz->sem);
  44. free (thiz);
  45. thiz = NULL;
  46. return;
  47. }
  48. static void info_init (PrivInfo* thiz)
  49. {
  50. return_if_fail (thiz != NULL);
  51. thiz->lock_var = 0;
  52. thiz->end_time = time(NULL) + 10;
  53. sem_init (&thiz->sem, 0,  1);
  54. return;
  55. }
  56. static void* pthread_func_1 (PrivInfo* thiz)
  57. {
  58. return_if_fail(thiz != NULL);
  59. int i = 0;
  60. while (time(NULL) < thiz->end_time)
  61. {
  62. sem_wait (&thiz->sem);
  63. printf ("pthread: pthread1 get lock./n");
  64. for (i = 0; i < 2; i ++)
  65. {
  66. thiz->lock_var ++;
  67. sleep (1);
  68. }
  69. sem_post (&thiz->sem);
  70. printf ("pthread1: pthread1 unlock/n");
  71. sleep (1);
  72. }
  73. return;
  74. }
  75. static void* pthread_func_2 (PrivInfo* thiz)
  76. {
  77. return_if_fail (thiz != NULL);
  78. while (time (NULL) < thiz->end_time)
  79. {
  80. sem_wait (&thiz->sem);
  81. printf ("pthread2: pthread2 get lock!/n");
  82. printf ("the lock_var = %d/n", thiz->lock_var);
  83. sem_post (&thiz->sem);
  84. printf ("phtread2: pthread2 unlock./n");
  85. sleep (3);
  86. }
  87. return;
  88. }

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

~~END~~

linux多线程学习(五)——信号量线程控制相关推荐

  1. linux多线程学习(六)——信号量实现同步

    在上一篇文章中已经用信号量来实现线程间的互斥,达到了互斥锁的效果,今天这篇文章将讲述怎样用信号量去实现同步. 信号量的互斥同步都是通过PV原语来操作的,我们可以通过注册两个信号量,让它们在互斥的问题上 ...

  2. Linux多线程的同步-----信号量和互斥锁

    前面两篇给基本概念讲过了,大家有兴趣的可以去看一下: Linux多线程_神厨小福贵!的博客-CSDN博客进程和线程的区别有哪些呢?进程是资源分配的最小单位,线程是CPU调度的最小单位进程有自己的独立地 ...

  3. C#多线程学习(五) 多线程的自动管理(定时器) (转载系列)——继续搜索引擎研究...

    Timer类:设置一个定时器,定时执行用户指定的函数.               定时器启动后,系统将自动建立一个新的线程,执行用户指定的函数. 初始化一个Timer对象: Timer timer ...

  4. Linux 多线程(一)线程概念:线程概念、线程与进程、线程间的独有与共享、多线程与多进程、线程控制

    线程概念 线程与进程 线程间的独有与共享 多线程与多进程 线程控制 线程概念 什么是线程 线程是进程中的一条执行流,执行程序中的某部分代码.linux下没有具体实现的线程,只有库函数用pcb来实现的线 ...

  5. linux多线程学习(二)——线程的创建和退出

    在上一篇文章中对线程进行了简单的概述,它在系统中和编程的应用中,扮演的角色是不言而喻的.学习它.掌握它.吃透它是作为一个程序员的必须作为.在接下来的讲述中,所有线程的操作都是用户级的操作.在LINUX ...

  6. java多线程学习一、线程介绍、线程创建的3种方式、lambda创建方式、线程状态、线程示例:12306买票和银行取钱

    文章目录 前言 一.线程简介 1.概述 2.进程.线程 区别 在这里插入图片描述 3. 核心概念 二. 线程创建 1.概述 2. 第一种方式继承Thread 1) 继承Thread 2) 示例:下载图 ...

  7. Java多线程系列(五):线程池的实现原理、优点与风险、以及四种线程池实现

    为什么需要线程池 我们有两种常见的创建线程的方法,一种是继承Thread类,一种是实现Runnable的接口,Thread类其实也是实现了Runnable接口.但是我们创建这两种线程在运行结束后都会被 ...

  8. Linux多线程编程:pthread线程创建、退出、回收、分离、取消

    文章目录 Linux线程 1.简单了解一下线程 2.线程创建:pthread_create 3.线程传参注意事项 4.线程退出:pthread_exit 5.线程回收:pthread_join 6.线 ...

  9. Java多线程学习八:线程池常用的阻塞队列

    线程池内部结构 线程池的内部结构主要由四部分组成,如图所示. 第一部分是线程池管理器,它主要负责管理线程池的创建.销毁.添加任务等管理操作,它是整个线程池的管家. 第二部分是工作线程,也就是图中的线程 ...

最新文章

  1. linux两种方式改变文件权限,Linux更改文件权限的两种方式
  2. Python3高并发定时更新任务进程池和线程池的使用
  3. 关于Public key for *.rpm is not installed 的解决方法
  4. putty连接虚拟fedaro失败的解决方法
  5. 使用 okHttp 3.0 版本前后的两点区别.(不要入坑哦)
  6. Apache ab 压力测试工具
  7. 这五本热门网络小说,竟然三本在第四届橙瓜网络文学奖评选目前排在前五!
  8. 电子计算机经历的四个阶段,电子计算机的发展经历了四代,其划分依据是什么?,计算机发展的四个阶段...
  9. [luogu3505][bzoj2088][POI2010]TEL-Teleportation【分层图】
  10. ScheduledExecutorService:多线程任务调度
  11. echarts(一)之地图连线动效
  12. centos6下安装配置NFS
  13. 【一日一logo_day_24】Phoenix??
  14. 【算法百题之四十二】罗马数字转整数
  15. matlab三维曲线的绘制
  16. Java splash screen
  17. oracle 12C ADG Far Sync 配置实验
  18. opencv+python 图片文字识别
  19. #即时通讯#实现消息已读回执功能的思路与实现
  20. BSP3 电力监控仪(功率监控仪)端子定义和接线

热门文章

  1. Windows IP测试小脚本
  2. 工控软件IFIX加入WEB显示图表
  3. 中移4G模块-ML302-OpenCpu开发-GPIO
  4. android adb音频采集,android adb
  5. asp 更新 mysql数据库_ASP如何使用MYSQL数据库
  6. 【算法•日更•第三十期】区间动态规划:洛谷P4170 [CQOI2007]涂色题解
  7. 一加7pro保存的录音文件在哪一个文件夹?
  8. 用servlet进行用户名和密码校验
  9. 【javascript】对原型对象、原型链的理解
  10. shiro源码篇 - 疑问解答与系列总结,你值得拥有