使用信号量控制线程互斥和同步。

首先要知道PV原语的概念。以下是百度百科对PV原语的介绍:

PV原语通过操作信号量来处理进程间的同步与互斥的问题。其核心就是一段不可分割不可中断的程序。

信号量的概念1965年由著名的荷兰计算机科学家Dijkstra提出,其基本思路是用一种新的变量类型(semaphore)来记录当前可用资源的数量。有两种实现方式:1)semaphore的取值必须大于或等于0。0表示当前已没有空闲资源,而正数表示当前空闲资源的数量;2) semaphore的取值可正可负,负数的绝对值表示正在等待进入临界区的进程个数。

信号量是由操作系统来维护的,用户进程只能通过初始化和两个标准原语(P、V原语)来访问。初始化可指定一个非负整数,即空闲资源总数。

P原语:P是荷兰语Proberen(测试)的首字母。为阻塞原语,负责把当前进程由运行状态转换为阻塞状态,直到另外一个进程唤醒它。操作为:申请一个空闲资源(把信号量减1),若成功,则退出;若失败,则该进程被阻塞;

V原语:V是荷兰语Verhogen(增加)的首字母。为唤醒原语,负责把一个被阻塞的进程唤醒,它有一个参数表,存放着等待被唤醒的进程信息。操作为:释放一个被占用的资源(把信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之。


可以看出其实是使用PV操作信号量,然后根据信号量的数值决定该线程是堵塞或者执行。

Linux实现了POSIX的无名信号量。常用的函数有以下几个:

  • sem_init:用来创建一个信号量,并初始化它的值。

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

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

  • sem_getvalue:用于得到信号量的值。
  • sem_destroy:用于删除信号量。

其中sem_init函数所需要的头文件是:#include < semaphore.h>,其他的函数所需要的头文件是:#include < pthread.h>

sem_init函数原型如下:

int sem_init(sem_t* sem,int pshared,unsigned int value)

各个参数的含义如下:
- sem:信号量。
- pshared:决定信号量能否在几个进程间共享。
- value:信号量的初始值。

其他的函数比如:sem_wait(sem_t* sem)都是有一个参数:sem_t* sem,也就是所要操作的信号量。

这些函数调用成功的话返回0,失败返回-1.


互斥

如果要用信号量来控制线程的互斥的话,那么就可以使用sem_init初始化一个值为1的信号量,然后两个线程分别使用sem_wait和sem_post对该信号量进行增加或者减少。如果线程一先使用sem_wait的话,那么此时信号量的值就是0了,线程二执行sem_wait之后发现值为-1根据P原语就会将这个线程阻塞,直到线程一执行sem_post将信号量的值增加一等于0并且唤醒等待的线程二,执行线程二的代码。而此时如果线程一再次执行sem_wait的话信号量的值又成了-1,线程一就被挂起了,知道线程二执行sem_post之后,信号量值为0并唤醒线程一。

大致流程如下:

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值