1、信号量概述
信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。
当信号量值大于 0 时,则可以访问,否则将阻塞。
PV 原语是对信号量的操作,一次 P 操作使信号量减1,一次 V 操作使信号量加1。
号量数据类型为:sem_t
信号量用于互斥:
不管多少个任务互斥 只需要一个信号量。先P 任务 在 V
信号量用于同步:
有多少个任务 就需要多少个信号量。最先执行的任务对应的信号量为1,其他信号量全部为0。每任务先P自己 任务 V下一个任务的信号量
2、信号量的API
1、初始化信号量
#include<semaphore.h>
int sem_init(sem_t* sem,int pshared,unsigned int value)
功能:
创建一个信号量并初始化它的值。一个无名信号量在被使用前必须先初始化。
参数:
sem:信号量的地址
pshared:等于 0,信号量在线程间共享(常用);不等于0,信号量在进程间共享。
value:信号量的初始值
返回值:
成功:0
失败: - 1
2、信号量减一 P操作
int sem_wait(sem_t* sem);
功能:
将信号量减一,如果信号量的值为0 则阻塞,大于0可以减一
参数:
信号量的地址
返回值:
成功返回0 失败返回-1
尝试对信号量减一
int sem_trywait(sem_t* sem);
功能:
尝试将信号量减一,如果信号量的值为0 不阻塞,立即返回 ,大于0可以减一
参数:
信号量的地址
返回值:
成功返回0
失败返回-1
3、信号量加一 V操作
int sem_post(sem_t* sem);
功能:
将信号量加一
参数:
信号量的地址
返回值:
成功返回0 失败返回-1
4、销毁信号量
int sem_destroy(sem_t* sem);
功能:
销毁信号量
参数:
信号量的地址
返回值:
成功返回0
失败返回-1
示例代码 信号量用于线程的互斥
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>
//定义一个信号量(用于互斥)
sem_t sem;
void my_printf(char* str)
{
int i = 0;
while (str[i] != '\0')
{
printf("%c", str[i++]);
fflush(stdout);
sleep(1);
}
return;
}void* task_fun01(void*arg)
{
//P 操作
sem_wait(&sem);
my_printf((char *)arg);
//V 操作
sem_post(&sem);
return NULL;
}
void* task_fun02(void* arg)
{
//P 操作
sem_wait(&sem);
my_printf((char *)arg);
//V 操作
sem_post(&sem);
return NULL;
}
void* task_fun03(void* arg)
{
//P 操作
sem_wait(&sem);
my_printf((char *)arg);
//V 操作
sem_post(&sem);
return NULL;
}
int main(int argc,char const* argv[])
{
//信号量初始化为1 第二个参数0表示用于线程
sem_init(&sem, 0, 1);
pthread_t tid1, tid2, tid3;
pthread_create(&tid1, NULL, task_fun01, "hello");
pthread_create(&tid2, NULL, task_fun02, " world ");
pthread_create(&tid3, NULL, task_fun03, " beijing ");
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
//销毁信号量
sem_destroy(&sem);
return 0;
}
示例代码 信号量用于线程的同步
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>
//定义三个信号量(用于同步)
sem_t sem1;
sem_t sem2;
sem_t sem3;
void my_printf(char* str)
{
int i = 0;
while (str[i] != '\0')
{
printf("%c", str[i++]);
fflush(stdout);
sleep(1);
}
return;
}
void* task_fun01(void*arg){
//P 操作
sem_wait(&sem1);
my_printf((char *)arg);
//V 操作
sem_post(&sem2);
return NULL;
}
void* task_fun02(void* arg)
{
//P 操作
sem_wait(&sem2);
my_printf((char *)arg);
//V 操作
sem_post(&sem3);
return NULL;
}
void* task_fun03(void* arg) {
//P 操作
sem_wait(&sem3);
my_printf((char *)arg);
//V 操作
sem_post(&sem1);
return NULL;
}
int main(int argc,char const* argv[])
{
//信号量初始化为1 第二个参数0表示用于线程
sem_init(&sem1, 0, 1);
sem_init(&sem2, 0, 0);
sem_init(&sem3, 0, 0);
pthread_t tid1, tid2, tid3;
pthread_create(&tid1, NULL, task_fun01, "hello");
pthread_create(&tid2, NULL, task_fun02, " world ");
pthread_create(&tid3, NULL, task_fun03, " beijing ");
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
//销毁信号量
sem_destroy(&sem);
return 0;
}