Linux 线程——信号量

题目:编写代码实现编写一个程序,开启三个线程,这三个线程的ID分别是A,B,C,每个线程将自己的ID在屏幕上打印10遍,要求输出必须按照ABC的顺序显示,如:ABCABCABC...

思路:创建三个ID分别为ABC的线程,定义三个信号量,利用信号量减值0时会堵塞这一特点来实现ABC顺序显示。具体是给A一个信号量,B和C设初始信号量为0,当A申请信号量,信号量减1成0,信号量A堵塞,这时对B释放信号量,开始执行线程B,当B也申请信号量减一变0造成堵塞时,C释放信号量,执行线程C.......一直循环.....

代码:

cpp 复制代码
#include<stdio.h>
#include<pthread.h>
#include<errno.h>
#include<semaphore.h>
#include<string.h>
pthread_t A,B,C;     //获取线程ID 
pthread_mutex_t lock;  //互斥锁 
sem_t sem1,sem2,sem3;  //定义信号量 
/*创建线程函数的目的是因为 线程创建函数pthread_create的第三个参数是一个函数指针*/ 
void *A_handler(void *arg)     //线程A函数 
{
    int  count = *((int *)arg);//线程执行次数,通过线程创建函数pthread_create的第四个参数获取 
   	while(count > 0)
    {
    	sem_wait(&sem1);        //为信号量sem1申请信号量,若申请成功信号量值减1 
    	//pthread_mutex_lock(&lock); //上锁 
      	printf("A...\n"); //申请成功输出A,A为线程A标识符 
        sleep(1);         //休眠1秒 
        count--;			//线程A执行次数减1 
        //pthread_mutex_unlock(&lock);//解锁 
        sem_post(&sem2); //释放信号量,信号量值加一。此操作是为了防止sem1将信号量申请完造成堵塞,因此这里让sem2释放信号量,始终保留一定信号量。 
	}
	pthread_exit("A...exit");//终止调用线程A 
}
void *B_handler(void *arg)  //线程B函数 
{
	int count = *((int *)arg); //线程B执行次数 通过线程创建函数pthread_create的第四个参数arg获取 
	
	while(count > 0)
	{
		sem_wait(&sem2);     //为sem2申请信号量,信号量 值减一 
		//pthread_mutex_lock(&lock);//上锁 
		printf("B...\n");//打印B申请成功的提示 
		sleep(1);//休眠1秒 
		count--;//线程B执行次数减1,直到不大于0,不再申请 
		//pthread_mutex_unlock(&lock);
		sem_post(&sem3);//同线程A函数,以释放信号量sem3来满足信号量sem2 申请所需的信号量,防止堵塞 
	}
	pthread_exit("B...exit");//终止调用线程B 
}
void *C_handler(void *arg)//线程C函数 
{
	int count = *((int *)arg);//线程C执行次数 通过线程创建函数pthread_create的第四个参数arg获取 
	
	while(count > 0)
	{
		sem_wait(&sem3);//为sem3申请信号量,信号量 值减一 
		//pthread_mutex_lock(&lock);//上锁 
		printf("C...\n");//输出提示,表示申请成功 
		sleep(1);//休眠,也可以说是延时 
		count--;// 线程C执行次数减1,直到不大于0,不再申请
		//pthread_mutex_unlock(&lock);
		sem_post(&sem1);//同线程A和B函数,以释放信号量sem1来满足信号量sem3申请所需的信号量,防止堵塞 
	}
	pthread_exit("C...exit");//终止线程C调用,打印终止字符提示 
}
int main(int argc,const char *argv[]) //参数用于对运行成功后传入终端输入参数的个数和名称 
{
	int arg1 = 10; //线程A执行次数 
	int arg2 = 10; //线程B执行次数 
	int arg3 = 10;//线程C执行次数 
	void *retval;  //非空指针,用于pthread_join函数返回线程标识 
	 /*信号量初始化,参数1为信号量标识符,参数2有两个值,为0时表示信号量用于同一进程多线程之间,非0时表示信号量由于进程与进程之间  参数3为信号量初始值 */
	 
	/*三个信号量分别设置1,0,0;基此循环*/ 
	if(sem_init(&sem1,0,1)<0)  //信号量sem1初始化 
	{                         
		perror("sem_init error");
	}
	
	if(sem_init(&sem2,0,0)<0)//信号量sem2初始化 
	{
		perror("sem_init error");
	}
	
	if(sem_init(&sem3,0,0)<0)//信号量sem3初始化 
	{
		perror("sem_init error");
	}
	
	/*线程创建函数pthread_create,共有四个参数,参数1为线程标识符,也叫线程ID;参数2指向一个结构体,为NULL时表示采用默认属性,参数3指向线程函数,参数4为参数3指向的函数传参。*/ 
	if(pthread_create(&A,NULL,A_handler,(void *)&arg1) != 0)  //创建ID为A,默认属性,指向线程函数A,传入参数(执行次数)为 arg1的线程 
	{
		perror("pthread_createA error");
		
	}
	if(pthread_create(&B,NULL,B_handler,(void *)&arg2) != 0)//创建ID为B,默认属性,指向线程函数B,传入参数(执行次数)为 arg2的线程 
	{
		perror("pthread_createB error");
		
	}
	if(pthread_create(&C,NULL,C_handler,(void *)&arg3) != 0)//创建ID为C,默认属性,指向线程函数C,传入参数(执行次数)为 arg3的线程 
	{
		perror("pthread_createC error");
		
	}
	/*pthread_join函数用于线程终止后返回非空指针retval保存的线程标识符 */
	pthread_join(A,&retval);           //返回线程A的标识符
	printf("%s\n",(char *)retval);     //输出线程标识符 
	
	pthread_join(B,&retval);
	printf("%s\n",(char *)retval);
	
	pthread_join(C,&retval);
	printf("%s\n",(char *)retval);
	
	sem_destroy(&sem1);  //摧毁信号量 
	sem_destroy(&sem2);
	sem_destroy(&sem3);
	
	//pthread_mutex_destory(&lock);
	return 0;
}

编译时要加后缀 -lpthread

cs 复制代码
gcc thread.c -o thread -lpthread

运行结果:

相关推荐
落落落sss7 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
简单.is.good25 分钟前
【测试】接口测试与接口自动化
开发语言·python
Yvemil71 小时前
MQ 架构设计原理与消息中间件详解(二)
开发语言·后端·ruby
程序员是干活的1 小时前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节
我是陈泽1 小时前
一行 Python 代码能实现什么丧心病狂的功能?圣诞树源代码
开发语言·python·程序员·编程·python教程·python学习·python教学
优雅的小武先生1 小时前
QT中的按钮控件和comboBox控件和spinBox控件无法点击的bug
开发语言·qt·bug
虽千万人 吾往矣1 小时前
golang gorm
开发语言·数据库·后端·tcp/ip·golang
创作小达人1 小时前
家政服务|基于springBoot的家政服务平台设计与实现(附项目源码+论文+数据库)
开发语言·python
郭二哈1 小时前
C++——list
开发语言·c++·list
杨荧1 小时前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源