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.......一直循环.....

代码:

#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

gcc thread.c -o thread -lpthread

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/226523.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(五) Python 代理模式

文章目录 5.1 代理模式概述5.1.1 代理介绍5.1.2 代理模式的作用 5.2 代理模式的UML类图5.3 了解不同类型的代理5.3.1虚拟代理5.3.2 远程代理5.3.3 保护代理5.3.4 智能代理 5.4 现实世界中的代理模式5.5 代理模式的优点5.6 门面模式和代理模式之间的比较 5.1 代理模式概述 5.1.…

【尘缘送书第五期】Java程序员:学习与使用多线程

目录 1 多线程对于Java的意义2 为什么Java工程师必须掌握多线程3 Java多线程使用方式4 如何学好Java多线程5 参与方式 摘要&#xff1a;互联网的每一个角落&#xff0c;无论是大型电商平台的秒杀活动&#xff0c;社交平台的实时消息推送&#xff0c;还是在线视频平台的流量洪峰…

Linux 防病毒软件:CentOS有哪些付费的防病毒软件

CentOS是一个基于开源的Linux发行版,通常不像Windows那样普遍需要使用付费的防病毒软件。大多数Linux系统侧重于使用开源和免费的安全工具来保护系统。一些常见的免费和开源的防病毒软件和安全工具包括ClamAV、Sophos Antivirus for Linux、rkhunter、chkrootkit等。 如果你非…

VSCode远程调试技巧,轻松Debug复杂深度学习项目

VSCode远程调试技巧&#xff0c;轻松Debug复杂深度学习项目 一、VSCode需要下载的插件 二、使用Remote SSH连接远程服务器 选择一个能运行的深度学习项目 三、修改Debug配置文件 点击create a launch.json file 右边是运行项目需要传入的参数&#xff0c;左边是Debug的配置…

C语言--不使用库函数,把一个数字转为字符串【详细解释】

一.题目描述 输入一个数字&#xff0c;把他转为字符串 比如&#xff1a;输入数字&#xff1a;12345 输出&#xff1a;12345&#xff08;这里的12345是字符串12345&#xff09; 二.思路分析 比如给定一个数字12345&#xff0c;先把它转为字符54321&#xff08;“54321”&#…

【笔记】Clion 中运行 C/C++11 之 CMakeLists.txt 的配置

该文章记录第一次使用 Clion 时&#xff0c;对 CMakeLists 的配置&#xff0c;使其能够运行 C/C11 的代码。 一. CMakeLists.txt 的配置 1、首先我们在需要新建一个项目 2、填写新建项目相关的信息 3、修改 CMakeLists.txt 文件内容 替换文本&#xff1a; # 使用此 CMakeLis…

无敌是多么的寂寞!一本书讲透Java多线程!吊打多线程从原理到实践!

摘要 互联网的每一个角落&#xff0c;无论是大型电商平台的秒杀活动&#xff0c;社交平台的实时消息推送&#xff0c;还是在线视频平台的流量洪峰&#xff0c;背后都离不开多线程技术的支持。在数字化转型的过程中&#xff0c;高并发、高性能是衡量系统性能的核心指标&#xff…

ZKP Understanding Nova (2) Relaxed R1CS

Understanding Nova Kothapalli, Abhiram, Srinath Setty, and Ioanna Tzialla. “Nova: Recursive zero-knowledge arguments from folding schemes.” Annual International Cryptology Conference. Cham: Springer Nature Switzerland, 2022. Nova: Paper Code 2. Unders…

配置应用程序监听器[org.springframework.web.context.ContextLoaderListener]错误

首先查看自己的配置文件(我maven项目) web.xml(内容除了文件的配置位置外&#xff0c;是否有其他的不同) <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3…

初始类与对象

初始类与对象 实验介绍 本课程是进一步对类与对象的深入认识&#xff0c;如何定义并实例化一个类&#xff0c;介绍如何使用 C 标准库 string 类等。 知识点 认识类与对象内联函数string 类类的定义与实例化 认识类与对象 官方定义 类&#xff1a;在面向对象编程中是一种…

【C语言快速学习基础篇】之一基础类型、进制转换、数据位宽

文章目录 一、基础类型(根据系统不同占用字节数会有变化)1.1、有符号整形1.2、无符号整形1.3、字符型1.4、浮点型1.5、布尔型 二、进制转换2.1、二进制2.2、八进制2.3、十进制2.4、十六进制2.5、N进制2.6、进制转换关系对应表 三、数据位宽3.1、位3.2、字节3.3、字3.4、双字3.5…

Java + Selenium + Appium自动化测试

一、启动测试机或者Android模拟器&#xff08;Genymotion俗称世界上最快的模拟器&#xff0c;可自行百度安装&#xff09; 二、启动Appium&#xff08;Appium环境安装可自行百度&#xff09; 三、安装应用到Genymotion上&#xff0c;如下图我安装一个计算机的小应用&#xff0c…

【android开发-05】android中activity的启动模式介绍

1&#xff0c;活动的启动模式 在 Android 中&#xff0c;Activity 的启动模式主要有以下四种&#xff1a; 默认启动模式&#xff08;Normal&#xff09;&#xff1a;这是默认的启动模式&#xff0c;基本上就是标准的启动模式。当一个 Activity 启动后&#xff0c;它将会被压入…

C51--IIC协议

IIC协议初识&#xff1a; 1、概述 IIC全称Inter-Integrated Circuit (集成电路总线) 是由PHILIPS公司在80年代开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备。 IIC属于半双工同步通信方式 SCL——时钟信号 SDA——数据信号 2、特点&#xff1a; 简单性和…

堆栈,BSS,DATA,TEXT

一、目标文件 首先目标文件的构成&#xff0c;Linux下就是.o 文件 编译器编译源码后生成的文件叫目标文件&#xff08;Object File&#xff09;。 目标文件和可执行文件一般采用同一种格式&#xff0c;这种存储格式为 ELF。 目前文件的内容至少有编译后的机器指令代码和数据&a…

leetcode 622. 设计循环链表

这道题讲了两种方法&#xff0c;第一个代码是用数组实现的&#xff0c;第二个是用链表实现的&#xff0c;希望对你们有帮助 &#xff08;最好在VS自己测试一遍&#xff0c;再放到 leetcode上哦&#xff09; 下面的是主函数&#xff08;作参考&#xff09;&#xff0c;静下心来…

第二十一章——网络通信

一.网络程序设计基础 1.局域网与互联网 2.网络协议 1.IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。 1.1 TCP/IP层次结构 2.TCP与UDP协议 TCP可保证数据从一端送至另一端时&#xff0c;能够确实送达&#xff0c;而且抵达的数据的排列顺序和送出时的顺序相…

AWR1642 boost开发板支持的TI参考设计

打开radar_toolbox_1_30_00_05\source\ti\examples\examples_overview,通过输入“1642”查找AWR1642 BOOST支持的参考设计,通过筛选,支持AWR1642 BOOST的参考设计如下: 挑选出两个参考设计上手,一个是“nonos_oob_16xx",不带OS;另一个是”short range radar“,比较…

吹响AI技术应用的号角

毫无疑问&#xff0c;各企业正围绕各种技术展开一场持续不断的角逐&#xff0c;力争率先取得领先且具创新性的技术进步&#xff0c;AI技术也不例外。疫情期间&#xff0c;全球各地企业的员工纷纷转向居家办公。因此&#xff0c;为轻松实现这一转型并建立起远程办公的新常态&…

用23种设计模式打造一个cocos creator的游戏框架----(四)装饰器模式

1、模式标准 模式名称&#xff1a;装饰器模式 模式分类&#xff1a;结构型 模式意图&#xff1a;动态地给一个对象添加一些额外的职责。就增加功能来说&#xff0c;装饰器模式比生成子类更为灵活。 结构图&#xff1a; 适用于&#xff1a; 当需要给一个对象在运行时添加更…