Linux 多线程:信号量

  之前我们介绍了互斥锁和条件变量的组合使用来实现线程的同步与互斥,本文使用信号量来实现进程(或线程)同步与互斥。

  使用互斥锁和条件变量实现同步互斥时,条件变量负责阻塞与唤醒进程,互斥锁负责给临界资源加锁与解锁。

  信号量实现同步互斥时,并没有分工,而是自己实现了进程的阻塞与唤醒,同时还负责给临界资源加锁解锁。

一、理解信号量

  信号量中含有计时器和pcb等待队列,计数器记录了空闲资源的数量。

  信号量的操作有两种:

  • P操作:当进程(或线程)要访问资源前,首先进行P操作:如果计数大于0,说明有空闲资源,将计数减1后返回。如果计数小于等于0,说明没有空闲资源了。
  • V操作:使用完毕资源后,要进行V操作。V操作会把该资源的计数器加1,代表现在多了一个空闲资源。如果之前有其他进程在申请此资源时由于没有空闲资源而阻塞,那么就唤醒一个被阻塞的进程。(如果有的话)

二、信号量实现同步互斥

信号量是怎样实现同步互斥的?

  • 互斥:将信号量的计数器设置为1,代表临界资源只有1个。访问资源前进行P操作,如果P操作成功,说明我们可以使用临界资源了,如果P操作失败就会阻塞,因为此时临界资源正在被使用。临界资源使用完毕后进行V操作,V操作会将计数器加1,并且唤醒一个正在阻塞等待该资源的进程。(如果有的话)

  • 同步:使用资源之前要进行P操作,代表资源被使用了。资源使用完毕后进行V操作,代表资源空闲了,那些阻塞的进程可以去使用了。

信号量使用流程: 定义信号量,初始化信号量,P操作,V操作,释放信号量

三、信号量相关接口

  1. 定义信号量

sem_t my_sem

 信号量是一个 sem_t 类型的变量。

  1. 初始化信号量

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

  • sem_t *sem:信号量
  • int pshared:0是线程间通信,非0是进程间通信
  • int val:信号量的初始值

 返回值: 成功返回0; 失败返回-1

  1. P操作

(1)int sem_wait(sem_t *sem)

 作用:如果计数器小于等于0,会阻塞进程。否则将计数器减1后返回。

  • sem_t *sem:信号量

(2)int sem_trywait(sem_t *sem)

 作用:如果计数器小于等于0,不会阻塞进程,而是直接返回。

  • sem_t *sem信号量

(3)int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)

 作用:如果计数器小于等于0,阻塞进程,但有限制时长。

  • sem_t *sem:信号量
  • const struct timespec *abs_timeout:规定的阻塞时间长度
  1. V操作

int sem_post(sem_t *sem)

 作用:将计数器加1。

  • sem_t *sem:信号量

5.释放信号量

int sem_destroy(sem_t *sem)

 作用:释放信号量

  • sem_t *sem:要释放的信号量

猜你喜欢

转载自blog.csdn.net/weixin_57761086/article/details/128805575