关键词:
文章目录
semaphore 信号量、信号灯
定义
有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。
目的
类似计数器,常用在多线程同步任务上,信号量可以在当前线程某个任务完成后,通知别的线程,再进行别的任务。
分类
二值信号量:信号量的值只有0和1,这和互斥量很类似,若资源被锁住,信号量的值为0,若资源可用,则信号量的值为1;
计数信号量:信号量的值在0到一个大于1的限制值之间,该计数表示可用的资源的个数。
信号量在创建时需要设置一个初始值,表示同时可以有几个任务可以访问该信号量保护的共享资源,初始值为1就变成互斥锁Mutex,即同时只能有一个任务可以访问信号量保护的共享资源
函数使用
首先需要include <semaphore.h>
这个库,没啥好说的,除非你自己实现内部函数。和互斥锁一样,也是四大金刚。(编译的时候需要加上-lpthread
)
sem_init 创建信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem_post
第一个参数:指向的信号对象
第二个参数:控制信号量的类型,如果其值为0,就表示信号量是当前进程的局部信号量,否则信号量就可以在多个进程间共享
第三个参数:信号量sem的初始值
返回值:success为0,failure为-1
sem_post 信号量的值加1
int sem_post(sem_t *sem);
第一个参数:信号量对象
返回值:success为0,failure为-1
sem_wait 信号量的值加-1
int sem_wait(sem_t *sem);
第一个参数:信号量对象
返回值:success为0,failure为-1
sem_destroy 用完记得销毁哦~
int sem_destroy(sem_t *sem);
第一个参数:信号量对象
返回值:success为0,failure为-1
示例程序1:进行三个下载任务,但是最多选择同时执行二个(创建两个线程)
(我对原作者的代码进行了一些改造)
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
//#include <windows.h>
#define MAXNUM 2
sem_t semDownload;
pthread_t a_thread, b_thread, c_thread;
int g_phreadNum = 1;
void InputInfo(void)
printf("****************************************\\n");
printf("*** which task you want to download? ***\\n");
printf("*** you can enter [1-3],[0] is done ***\\n");
printf("****************************************\\n");
void *func1(void *arg)
int ret;
//等待信号量的值>0
ret = sem_wait(&semDownload);
if(ret != 0)
printf("error, sem_wait failed\\n");
printf("============== Downloading Task 1 ============== \\n");
sleep(5);
printf("============== Finished Task 1 ============== \\n");
g_phreadNum--;
//等待线程结束
//pthread_join(a_thread, NULL);
void *func2(void *arg)
int ret;
ret = sem_wait(&semDownload);
if(ret != 0)
printf("error, sem_wait failed\\n");
printf("============== Downloading Task 2 ============== \\n");
sleep(3);
printf("============== Finished Task 2 ============== \\n");
g_phreadNum--;
//pthread_join(b_thread, NULL);
void *func3(void *arg)
int ret;
ret = sem_wait(&semDownload);
if(ret != 0)
printf("error, sem_wait failed\\n");
printf("============== Downloading Task 3 ============== \\n");
sleep(1);
printf("============== Finished Task 3 ============== \\n");
g_phreadNum--;
//pthread_join(c_thread, NULL);
int main()
int ret;
int taskNum;
InputInfo();
//初始化信号量
ret = sem_init(&semDownload, 0, 0);
if(ret != 0)
printf("error, sem_init failed\\n");
while (scanf("%d", &taskNum) != EOF)
//输入0,判断是否正常退出
if (taskNum == 0)
if (g_phreadNum <= 1)
break;
else
printf("Can not quit, casue count of threads is [%d]\\n", g_phreadNum - 1);
printf("your choose Downloading Task [%d]\\n", taskNum);
//线程数超过2个则不下载
if (g_phreadNum > MAXNUM)
printf("!!! You've reached a limit on the number of threads !!!\\n");
continue;
//用户选择下载Task
switch (taskNum)
case 1:
//创建线程1
pthread_create(&a_thread, NULL, func1, NULL);
//信号量+1,进而触发fun1的任务
ret = sem_post(&semDownload);
if(ret != 0)
printf("error, sem_post failed\\n");
//总线程数+1
g_phreadNum++;
break;
case 2:
pthread_create(&b_thread, NULL, func2, NULL);
ret = sem_post(&semDownload);
if(ret != 0)
printf("error, sem_post failed\\n");
g_phreadNum++;
break;
case 3:
pthread_create(&c_thread, NULL, func3, NULL);
ret = sem_post(&semDownload);
if(ret != 0)
printf("error, sem_post failed\\n");
g_phreadNum++;
break;
default:
printf("!!! eroor task [%d] !!!\\n", taskNum);
break;
//销毁信号量
sem_destroy(&semDownload);
if(ret != 0)
printf("error, sem_destroy failed\\n");
return 0;
CentOS编译运行结果:
[root@localhost 20220816]# ./a.out
****************************************
*** which task you want to download? ***
*** you can enter [1-3],[0] is done ***
****************************************
1
your choose Downloading Task [1]
============== Downloading Task 1 ==============
============== Finished Task 1 ==============
2
your choose Downloading Task [2]
============== Downloading Task 2 ==============
3
your choose Downloading Task [3]
============== Downloading Task 3 ==============
============== Finished Task 2 ==============
4============== Finished Task 3 ==============
your choose Downloading Task [4]
!!! eroor task [4] !!!
5
your choose Downloading Task [5]
!!! eroor task [5] !!!
1
your choose Downloading Task [1]
============== Downloading Task 1 ==============
2
your choose Downloading Task [2]
============== Downloading Task 2 ==============
3
your choose Downloading Task [3]
!!! You've reached a limit on the number of threads !!!
============== Finished Task 1 ==============
============== Finished Task 2 ==============
4
your choose Downloading Task [4]
!!! eroor task [4] !!!
示例程序:单生产者单消费者模型
简介:一个线程生产,另一个线程消费,线程A生产完后立马给线程B发信号,线程B收到后立即回应线程A,告诉它我收到了,发送100000次
(test_semaphore_1_1.c)
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include "unistd.h"
#include <string.h>
#define printf(format, ...) \\
do \\
char str[1024] = 0; \\
struct timeval tv; \\
struct tm* t; \\
gettimeofday(&tv, NULL); \\
t = localtime(&tv.tv_sec); \\
sprintf(str,"[%04d-%02d-%02d %02d:%02d:%02d.%03ld] ", \\
1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, \\
t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000); \\
printf("%s", str); \\
printf("#%d "format, __LINE__, ##__VA_ARGS__); \\
while (0)
#define LIM (100000)
sem_t sem, sem_R;
int count = 0;
int count_R = 0;
void* f_producer(void *arg)
sleep(1);
int ret;
while(1)
printf("[%s] produce start\\n", __FUNCTION__);
//信号量+1,进而触发fun1的任务
printf("[%s] produce finish, sem_post\\n", __FUNCTION__);
ret = sem_post(&sem);
if(ret != 0)
printf("[%s] error, sem_post failed\\n", __FUNCTION__);
break;
count++;
printf("\\n[%s] count = %d\\n", __FUNCTION__, count);
if(count == LIM)
printf("[%s] break\\n", __FUNCTION__);
break;
printf("[%s] waiting for sem_R\\n", __FUNCTION__);
ret = sem_wait(&sem_R);
if(ret != 0)
printf("[%s] error, sem_wait failed\\n", __FUNCTION__);
break;
printf("[%s] received sem_R\\n", __FUNCTION__);
void* f_consumer(void *arg)
sleep(1);
int ret;
while(1)
printf("[%s] waiting for sem\\n", __FUNCTION__);
ret = sem_wait(&sem);
if(ret != 0)
printf("error, sem_wait failed\\n");
break;
printf("[%s] received sem\\n", __FUNCTION__);
count_R++;
printf("\\n[%s] count_R = %d\\n", __FUNCTION__, count_R);
if(count_R == LIM)
printf("[%s] break\\n", __FUNCTION__);
break;
printf("[%s] return start\\n", __FUNCTION__);
ret = sem_post(&sem_R);
if(ret != 0)
printf("[%s] error, sem_post failed\\n", __FUNCTION__);
break;
int main()
int ret;
pthread_t consumer, producer;
//初始化信号量
ret = sem_init(&sem, 0, 0);
if(ret != 0)
printf("error, sem_init failed\\n");
//创建线程
pthread_create(&producer, NULL, f_producer, NULL);
pthread_create(&consumer, NULL, f_consumer, NULL);
ret = pthread_join(producer, NULL);
if(ret != 0)
printf("error, join failed, ret = [%d]\\n", ret);
ret = pthread_join(consumer, NULL);
if(ret != 0)
printf("error, join failed, ret = [%d]\\n", ret);
//销毁信号量
sem_destroy(&sem);
if(ret != 0)
printf("error, sem_destroy failed\\n");
return 0;
编译运行:
[root@localhost 20220817]# gcc test_semaphore_1_1.c -lpthread
[root@localhost 20220817]# ./a.out
结果:
总共只花费了10秒钟就跑完了,且无信号丢失,还是很稳定的(比那个啥互斥锁+条件变量好用多了lll…)
示例程序:多生生产者多消费者模型
(略,后更。。。)
总结
这用来做线程间通知,不比锁加条件变量好用多了啊!!!!那个一大堆,还挺麻烦的,,,,,,
c语言编程—semaphore信号量操作(代码片段)
目录文章目录目录信号量二元信号量semaphore.h库sem_init()sem_wait()sem_post()示例程序信号量信号量(semaphore)是一种常被用于多线程或多进程场景中的同步机制,用于保证多线程或多进程对共享数据的读/写操作是顺序的。... 查看详情
12第七周-网络编程-线程中的信号量(semaphore)
...同时允许一定数量的线程更改数据。简单介绍如下: 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。而互斥锁是用在多线程多任务互斥的,一个线程占用... 查看详情
java多线程-信号量
Semaphore(信号量)是一个线程同步结构,用于在线程间传递信号,以避免出现信号丢失,或者像锁一样用于保护一个关键区域。自从5.0开始,jdk在java.util.concurrent包里提供了Semaphore的官方实现,因此大家不需要自己去实现Semaphore... 查看详情
java多线程并发工具类-信号量semaphore对象讲解
...》系列之《并发工具类》教程的第三篇:《Java多线程下信号量》。一:Semaphore是什么?Semaphore中文意思:信号量。来看看JavaAPI中对semaphore对象的解释: 什么意思呢?简单理解来说,Semaphore:信号量主要用于两个目的:一个是... 查看详情
经典线程同步信号量semaphore
...t、互斥量Mutex在经典线程同步问题中的使用。本篇介绍用信号量Semaphore来解决这个问题。首先也来看看如何使用信号量,信号量Semap 查看详情
java核心-多线程-并发控制器-semaphore信号量
...er多线程组件),它相当于是一个并发控制器,是用于管理信号量的。构造的时候传入可供管理的信号量的数值,这个数值就是控制并发数量的,就是同时能几个线程访问。我们需要控制并发的代码,执行前先通过acquire方法获取... 查看详情
秒杀多线程第八篇经典线程同步信号量semaphore
...t、互斥量Mutex在经典线程同步问题中的使用。本篇介绍用信号量Semaphore来解决这个问题。首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便。下面是这几个函数的原型和使用说明。第一个 CreateSemaphore... 查看详情
java并发多线程编程——semaphore(代码片段)
...二、Semaphore代码示例一、Semaphore概述Semaphore的字面意思是信号量。Semaphore主要用于两个目的:(1)、一个是用于多个共享资源的相互排斥使用。(2)、另一个用于并发资源数的控制.。二、Semaphore代码示例模... 查看详情
网络编程基础--多线程---concurrent.futures模块---事件event---信号量semaphore---定时器timer---死锁现象递归锁----线程队列queue(示例代码
1 concurrent.futures模块:#fromabcimportabstractmethod,ABCMeta##classA(metaclass=ABCMeta):#defmai(self):#pass#@classmethod#classB(A):#defmai(self):#pass#抽象类----定义子类的一些接口标准@abstractmethod============ 查看详情
009-多线程-锁-juc锁-semaphore信号量(代码片段)
一、概述 Semaphore是一个计数信号量。从概念上将,Semaphore包含一组许可证。如果有需要的话,每个acquire()方法都会阻塞,直到获取一个可用的许可证。每个release()方法都会释放持有许可证的线程,并且归还Semaphore一个可用的... 查看详情
秒杀多线程第八篇经典线程同步信号量semaphore(代码片段)
...t、互斥量Mutex在经典线程同步问题中的使用。本篇介绍用信号量Semaphore来解决这个问题。首先也来看看如何使用信号量,信号量Semap 查看详情
c#多线程のsemaphore(信号量,负责协调各个线程)
Semaphore负责协调线程,可以限制对某一资源访问的线程数量 这里对SemaphoreSlim类的用法做一个简单的例子:namespaceWpfApplication6{///<summary>///MainWindow.xaml的交互逻辑///</summary>publicpartialclassMainWindow:Window{staticSemaph 查看详情
多线程加锁(代码片段)
...atch_semaphore_signaldispatch_semaphore_waitdispatch_semaphore_create创建信号量dispatch_semaphore_create(longvalue);给信号量初始一个值,当传递的值小于0,信号量将初始化失败返回NULL。dispatch_semaphore_tsemaphore=dispatch_semaphore_create(0);dispatch_se... 查看详情
多线程(十三aqs原理-semaphore信号量)(代码片段)
Semaphore介绍Semaphore,限制对共享资源访问的最大线程数量,要访问共享资源,需要先申请许可,申请到许可才能访问。访问结果了,释放许可。案例:3个线程:Thread-1、Thread-2、Thread-3。一个许可数为2的公平策略的Semaphore。线程... 查看详情
java多线程信号量同步类countdownlatch与semaphore
信号量同步是指在不同线程之间,通过传递同步信号量来协调线程执行的先后次序。CountDownLatch是基于时间维度的Semaphore则是基于信号维度的。1:基于执行时间的同步类CountDownLatch 例如现有3台服务器,需编写一个获取各... 查看详情
并发编程中:semaphore信号量与lock的区别(代码片段)
Semaphore,信号量,常用于限制可以访问某些资源的线程数量,比如连接池、对象池、线程池等等。其中,你可能最熟悉数据库连接池,在同一时刻,一定是允许多个线程同时使用连接池的,当然,每个连接在被释放前,是不允许... 查看详情
多线程编程:同时使用信号量与互斥锁
#include<pthread.h>#include<semaphore.h>#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<cerrno>#defineCUSTOMER_NUM10pthread_mutex_tmutex_x=PTHREAD_MUT 查看详情
c多线程编程信号处理
用linuxC编程的时候,处理信号在所难免。在多线程编程中需要注意两个函数的使用,一个是pthread_sigmask(),用来在线程中屏蔽某个信号;另一个是sigaction(),在线程中用来设置信号的处理方式。voidsig_handler1(intarg){ printf("thread1gets... 查看详情