线程同步与互斥:POSIX无名信号量

信号量概述

信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。

编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于 0 时,则可以访问,否则将阻塞。PV
原语
是对信号量的操作,一次 P 操作使信号量减1,一次 V 操作使信号量加1。

信号量主要用于进程或线程间的同步和互斥这两种典型情况。

信号量用于互斥:

信号量用于同步:

在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量。无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥。它们的区别和管道及命名管道的区别类似,无名信号量则直接保存在内存中,而有名信号量要求创建一个文件。

无名信号量基本操作

以下函数所需头文件:

#include <semaphore.h>

注意:编译信号量操作函数时,需要加上参数-lpthread

信号量数据类型为:sem_t

1)初始化信号量

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

功能:

创建一个信号量并初始化它的值。一个无名信号量在被使用前必须先初始化。

参数:

sem:信号量的地址。

pshared:等于 0,信号量在线程间共享(常用);不等于0,信号量在进程间共享。

value:信号量的初始值。

返回值:

成功:0

失败:-1

2)信号量 P 操作(减 1)

int sem_wait(sem_t *sem);

功能:

将信号量的值减 1。操作前,先检查信号量(sem)的值是否为 0,若信号量为 0,此函数会阻塞,直到信号量大于 0 时才进行减 1 操作。

参数:

sem:信号量的地址。

返回值:

成功:0

失败:-1

int sem_trywait(sem_t *sem);

以非阻塞的方式来对信号量进行减 1 操作。若操作前,信号量的值等于 0,则对信号量的操作失败,函数立即返回。

3)信号量 V 操作(加 1)

int sem_post(sem_t *sem);

功能:

将信号量的值加 1 并发出信号唤醒等待线程(sem_wait())。

参数:

sem:信号量的地址。

返回值:

成功:0

失败:-1

4)获取信号量的值

int sem_getvalue(sem_t *sem, int *sval);

功能:

获取 sem 标识的信号量的值,保存在 sval 中。

参数:

sem:信号量地址。

sval:保存信号量值的地址。

返回值:

成功:0

失败:-1

5)销毁信号量

int sem_destroy(sem_t *sem);

功能:

删除 sem 标识的信号量。

参数:

sem:信号量地址。

返回值:

成功:0

失败:-1

无名信号量应用实例

信号量用于互斥实例:

[cpp] view
plain
copy

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <unistd.h>
  4. #include <semaphore.h>
  5. sem_t sem; //信号量
  6. void printer(char *str)
  7. {
  8. sem_wait(&sem);//减一
  9. while(*str)
  10. {
  11. putchar(*str);
  12. fflush(stdout);
  13. str++;
  14. sleep(1);
  15. }
  16. printf("\n");
  17. sem_post(&sem);//加一
  18. }
  19. void *thread_fun1(void *arg)
  20. {
  21. char *str1 = "hello";
  22. printer(str1);
  23. }
  24. void *thread_fun2(void *arg)
  25. {
  26. char *str2 = "world";
  27. printer(str2);
  28. }
  29. int main(void)
  30. {
  31. pthread_t tid1, tid2;
  32. sem_init(&sem, 0, 1); //初始化信号量,初始值为 1
  33. //创建 2 个线程
  34. pthread_create(&tid1, NULL, thread_fun1, NULL);
  35. pthread_create(&tid2, NULL, thread_fun2, NULL);
  36. //等待线程结束,回收其资源
  37. pthread_join(tid1, NULL);
  38. pthread_join(tid2, NULL);
  39. sem_destroy(&sem); //销毁信号量
  40. return 0;
  41. }

运行结果如下:

信号量用于同步实例:

[cpp] view
plain
copy

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <pthread.h>
  4. #include <semaphore.h>
  5. sem_t sem_g,sem_p;   //定义两个信号量
  6. char ch = ‘a‘;
  7. void *pthread_g(void *arg)  //此线程改变字符ch的值
  8. {
  9. while(1)
  10. {
  11. sem_wait(&sem_g);
  12. ch++;
  13. sleep(1);
  14. sem_post(&sem_p);
  15. }
  16. }
  17. void *pthread_p(void *arg)  //此线程打印ch的值
  18. {
  19. while(1)
  20. {
  21. sem_wait(&sem_p);
  22. printf("%c",ch);
  23. fflush(stdout);
  24. sem_post(&sem_g);
  25. }
  26. }
  27. int main(int argc, char *argv[])
  28. {
  29. pthread_t tid1,tid2;
  30. sem_init(&sem_g, 0, 0);   //初始化信号量
  31. sem_init(&sem_p, 0, 1);
  32. pthread_create(&tid1, NULL, pthread_g, NULL);
  33. pthread_create(&tid2, NULL, pthread_p, NULL);
  34. pthread_join(tid1, NULL);
  35. pthread_join(tid2, NULL);
  36. return 0;
  37. }

运行结果如下:

本教程示例代码下载请点此处。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 11:38:12

线程同步与互斥:POSIX无名信号量的相关文章

Linux系统编程——线程同步与互斥:无名信号量

信号量概述 信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问. 编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于 0 时,则可以访问,否则将阻塞.PV 原语是对信号量的操作,一次 P 操作使信号量减1,一次 V 操作使信号量加1. 信号量主要用于进程或线程间的同步和互斥这两种典型情况. 信号量用于互斥: 信号量用于同步: 在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量.无名信号量一般用

线程同步(互斥锁与信号量的作用与区别)

“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里).而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源.比如对全局变量的访问,有时要加锁,操作完了,在解锁.有的时候锁和信号量会同时使用的” 也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后

C#学习笔记---线程同步:互斥量、信号量、读写锁、条件变量

http://www.cnblogs.com/maxupeng/archive/2011/07/21/2112282.html 一.互斥量(mutex) 互斥量本质上是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁. 对互斥量进行加锁以后,任何其它试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁.如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为运行状态的线程可以对互斥量加锁,其它线程将会看到互斥锁依然被锁住,只能回去再次

LinuxC线程pthread线程同步进程同步-互斥量、信号量、条件变量、读写锁、文件锁

1. 同步概念 2. 线程同步 3. 进程同步 4. 生产者消费者模型 5. 哲学家问题 原文地址:https://www.cnblogs.com/yongfengnice/p/12116954.html

线程间通信机制posix匿名信号量

信号量分为两种 一种是简单的信号量,另一种是用于进程间通信的信号量集. 简单的信号量 属于POSIX标准的信号量; 从信号量的命名来看,信号量又可分为命名信号量和匿名(未命名)信号量; 从信号量的值来看,信号量可分为二进制信号量和计数信号量; 1.匿名信号量和命名信号量: 匿名信号量是在内存中分配内存.进行初始化并由系统API进行管理的,它可以在多个线程之间进行资源同步,也可以在多个进程之间进行资源同步,这主要是看在初始化的时候给pshared传递的参数值,为0,则在线程之间同步,非0,则在进程

一起talk C栗子吧(第一百一十六回:C语言实例--线程同步之互斥量二)

各位看官们,大家好,上一回中咱们说的是线程同步之信号量的例子,这一回咱们继续说该例子.闲话休提,言归正转.让我们一起talk C栗子吧! 我们在上一回中详细介绍了互斥量相关函数的用法,这一回中,我们介绍如何使用这些函数来操作互斥量. 下面是详细的操作步骤: 1.定义一个互斥量A,用来同步线程: 2.在创建线程的进程中使用pthread_mutex_init函数初始化互斥量,互斥量的属性使用默认值: 3.在读取数据的线程中读取数据,首先使用pthread_mutex_lock函数对互斥量A进行加锁

Android多线程研究(3)——线程同步和互斥及死锁

为什么会有线程同步的概念呢?为什么要同步?什么是线程同步?先看一段代码: package com.maso.test; public class ThreadTest2 implements Runnable{ private TestObj testObj = new TestObj(); public static void main(String[] args) { ThreadTest2 tt = new ThreadTest2(); Thread t1 = new Thread(tt,

线程同步与互斥之条件·变量

条件变量(condition variable) 线程间的同步与互斥技术,主要以互斥锁和条件变量为主,条件变量和互斥所的配合使用可以很好的处理对于条件等待的线程间的同步问题.举个例子:消费者和生产者问题. 消费者与生产者最基本的关系是服务与被服务的关系,但是在线程同步与互斥中强调的是两者访问资源的关系.首先生产与消费的关系为:同步与互斥,生产与生产的关系为:互斥,消费与消费的关系为:互斥.所以维护这三种关系的有两类人:生产者与消费者.并且生产数据与消费数据必须有场所. 所以将其简述为三种关系两类

线程同步与互斥(POSIX信号量——环形数组实现生产者消费者模型)

Semaphore(信号量) Mutex变量是非0即1的,可看作一种资源的可用数量,初始化时Mutex是1,表示有一个可用资源,加锁时获得该资源,将Mutex减到0,表示不再有可用资源,解锁时释放该资源,将Mutex重新加到1,表示又有了一个可用资源. 信号量(Semaphore)和Mutex类似,表示可用资源的数量,和Mutex不同的是这个数量可以大于1.如果信号量描述的资源数目是1时,此时的信号量和互斥锁相同! POSIX semaphore库函数,这种信号量不仅可用于同一进程的线程间同步,