嵌入式学习第二十二天!(继续学习线程)

线程相关函数接口:

1. 线程分离属性:

    线程结束后,自动回收线程空间

    1. pthread_attr_init:

int pthread_attr_init(pthread_attr_t *attr);

        功能:线程属性初始化

    2. pthread_attr_destroy:

int pthread_attr_destroy(pthread_attr_t *attr);

        功能:线程属性销毁

    3. pthread_attr_setdetachstate:

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

        功能:设置分离属性

            PTHREAD_CREATE_DETACHED   分离属性
            PTHREAD_CREATE_JOINABLE   加入属性(默认)

    练习:

       1. 利用线程的分离属性创建三个线程,打印线程id

#include "head.h"

void *thread1(void *arg)
{
	printf("stat to thread1(tid:%#x)\n", (unsigned int)pthread_self());
	return NULL;
}

void *thread2(void *arg)
{
	printf("stat to thread2(tid:%#x)\n", (unsigned int)pthread_self());
	return NULL;
}

void *thread3(void *arg)
{
	printf("stat to thread2(tid:%#x)\n", (unsigned int)pthread_self());
	return NULL;
}

int main(void)
{
	int i = 0;
	pthread_t thread[3];
	void *(*p[3])(void *) = {thread1, thread2, thread3};
	pthread_attr_t attr;

	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	for(i = 0; i < 3; i++)
	{
		pthread_create(&thread[i], &attr, p[i], NULL);
	}
	pthread_attr_destroy(&attr);

	while(1)
	{

	}

}

        2. 首先定义一个学生结构体,包含姓名、性别、年龄、分数。再创建两个两个线程,线程1负责从终端接收学生信息,线程2负责将学生信息打印在终端。

#include "head.h"

struct studet
{
	char name[100];
	char sex;
	int age;
	int score;
};

void *InputInfo(void *arg)
{
	struct studet *stu = arg;
	char *ptmp = stu->name;

	fgets(stu->name, 100, stdin);
	ptmp[strlen(ptmp)-1] = '\0';

	scanf("%c", &stu->sex);
	scanf("%d", &stu->age);
	scanf("%d", &stu->score);

	return NULL;
}

void *OutputInfo(void *arg)
{
	struct studet *stu = arg;
	
    sleep(5);
	printf("%s\n", stu->name);
	printf("%c\n", stu->sex);
	printf("%d\n", stu->age);
	printf("%d\n", stu->score);
	
	return NULL;
}

int main(void)
{
	struct studet t;
	pthread_t input;
	pthread_t output;
	
	pthread_create(&input, NULL, InputInfo, &t);
	pthread_create(&output, NULL, OutputInfo, &t);

	pthread_join(input, NULL);
    pthread_join(output, NULL);

	return 0;
}

2. 线程互斥:

    1. 互斥锁:

        防止资源竞争

    2. 函数接口:

        1. pthread_mutex_init:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
           const pthread_mutexattr_t *restrict attr);

            功能:互斥锁初始化

            参数:

                mutex:互斥锁空间首地址
                attr:互斥锁的属性(默认为NULL)

            返回值:

                成功返回0 
                失败返回错误码

        2. pthread_mutex_destroy:
int pthread_mutex_destroy(pthread_mutex_t *mutex);

            功能:互斥锁销毁

            参数:

                mutex:互斥锁空间首地址

            返回值:

                成功返回0 
                失败返回错误码

        3. pthread_mutex_lock:
int pthread_mutex_lock(pthread_mutex_t *mutex);

            功能:上锁

        4. pthread_mutex_unlock:
int pthread_mutex_unlock(pthread_mutex_t *mutex);

            功能:解锁

    3. 临界资源、临界区:

        加锁解锁中间的代码称为临界资源、临界区

        同一时刻临界资源不能同时执行,只能执行其中一个临界资源代码

    4. 原子操作:

        CPU最小的一次不能被任务调度打断的操作称为原子操作

    5. 注意:

        互斥锁只能解决资源竞争的问题,无法同步代码(没有先后执行的顺序关系)

    练习:

        定义三个整型的全局变量Num1, Num2,val,创建两个线程,一个线程循环令Num1=val,Num2=val,val自加;另一个线程,循环判断:当Num1不等于Num2的时候,输出Num1和Num2的值。利用互斥锁,让Num1始终等于Num2,使终端没有输出。

#include "head.h"

int val = 0;
int Num1 = 0;
int Num2 = 0;
pthread_mutex_t lock;

void *thread1(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&lock);
		Num1 = val;
		Num2 = val;
		pthread_mutex_unlock(&lock);
		val++;
	}
	return NULL;
}
void *thread2(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&lock);
		if(Num1 != Num2)
		{
			printf("Num1 = %d, Num2 = %d\n", Num1, Num2);
		}
		pthread_mutex_unlock(&lock);
	}
	return NULL;
}


int main(void)
{
	pthread_t tid1;
	pthread_t tid2;
	
	pthread_mutex_init(&lock, NULL);

	pthread_create(&tid1, NULL, thread1, NULL);
	pthread_create(&tid2, NULL, thread2, NULL);

	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);

	pthread_mutex_destroy(&lock);
	
	return 0;
}

3. 死锁:

    多线程操作互斥锁,导致多个线程均违法向下执行的状态称为死锁状态,简称为死锁

    1. 死锁产生的四个必要条件:

        1. 互斥条件

        2. 不可剥夺条件

        3. 请求保持

        4. 循环等待

    2. 如何避免产生死锁:

        1. pthread_mutex_trylock 替代 pthread_mutex_lock

        2. 加锁顺序保持一致

4. 信号量:

    信号量是一种资源,可以被初始化、申请、释放、销毁

    P操作:申请资源

    V操作:释放资源

    1. sem_init:

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

        功能:初始化信号量

        参数:

            sem:信号量空间首地址

            pshared:为0的话,是一个进程中的所有线程间共享;非0的话,则是进程间共享

            value:初始化的值

        返回值:

           成功返回0 
           失败返回-1 

    2. sem_destory:

int sem_destroy(sem_t *sem);

        功能:信号量的销毁

        参数:

            sem:信号量空间首地址

        返回值:

            成功返回0 
            失败返回-1

    3. sem_wait:

int sem_wait(sem_t *sem);

        功能:申请信号量

    4. sem_post:

int sem_post(sem_t *sem);

        功能:释放信号量

作业:

        1. 创建三个线程分别循环打印 A B C,要求打印出来的顺序总是 A -> B -> C

#include "head.h"

sem_t sem_a;
sem_t sem_b;
sem_t sem_c;

void *thread1(void* arg)
{
	while(1)
	{
		sem_wait(&sem_a);
		printf("A\n");
		sem_post(&sem_b);
	}

	return NULL;
}
void *thread2(void* arg)
{
	while(1)
	{
		sem_wait(&sem_b);
		printf("B\n");
		sem_post(&sem_c);
	}

	return NULL;
}
void *thread3(void* arg)
{
	while(1)
	{
		sem_wait(&sem_c);
		printf("C\n");
		sem_post(&sem_a);
	}

	return NULL;
}

int main(void)
{
	int i = 0;
	pthread_t tid[3];
	void *(*p[3])(void *) = {thread1, thread2, thread3};
	
	sem_init(&sem_a, 0, 1);
	sem_init(&sem_b, 0, 0);
	sem_init(&sem_c, 0, 0);

	for(i = 0; i < 3; i++)
	{
		pthread_create(&tid[i], NULL, p[i], NULL);
	}

	for(i = 0; i < 3; i++)
	{
		pthread_join(tid[i], NULL);
	}

	sem_destroy(&sem_a);
	sem_destroy(&sem_b);
	sem_destroy(&sem_c);

	return 0;

}

        2. PTA | 程序设计类实验辅助教学平台

#include <stdio.h>

struct student
{
	char number[20];
	int testbit;
	int exambit;
};

int GetStudentBit(struct student *pstu, int maxlen)
{
	int n = 0;
	int i = 0;

	scanf("%d", &n);

	if(n > maxlen)
	{
		perror("Over to limit");
		return -1;
	}

	for(i = 0; i < n; i++)
	{
		scanf("%s %d %d", pstu[i].number, &pstu[i].testbit, &pstu[i].exambit);
	}

	return n;
}
int GetFoundBit(int *pbit, int maxlen)
{
	int m = 0;
	int i = 0;

	scanf("%d", &m);

	if(m > maxlen)
	{
		perror("Over to limit");
		return -1;
	}

	for(i = 0; i < m; i++)
	{
		scanf("%d", &pbit[i]);

	}
	return m;
}

int PrintStudentBit(struct student *pstu, int curlen, int *pfound, int m)
{
	int i = 0;
	int j = 0;

	for(i = 0; i < m; i++)
	{
		for(j = 0; j < curlen; j++)
		{
			if(pstu[j].testbit == pfound[i])
			{
				printf("%s %d\n", pstu[j].number, pstu[j].exambit);
			}
		}
	}
	
	return 0;

}

int main(void)
{
	struct student stu[1000];
	int curlen = 0;
	int bitinfo[1000];
	int foundnum = 0;
	
	curlen = GetStudentBit(stu, 1000);
	foundnum = GetFoundBit(bitinfo, 1000);
	
	PrintStudentBit(stu, curlen, bitinfo, foundnum);

	return 0;
}

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

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

相关文章

居然才发现!字节跳动旗下国产AI绘画工具Dreamina,这么好用居然还免费!(强烈推荐)

昨天看到群里说&#xff0c;剪映旗下类似 Sora 的 AI 视频生成工具 Dreamina 开放内测申请了&#xff0c;于是申请了下&#xff0c;顺道发现 Dreamina 还是一个宝藏的 AI 绘画工具。 Dreamina 是剪映旗下的一个 AI 创作平台&#xff0c;目前支持「图片生成」功能&#xff0c;也…

MWC 2024丨生成式AIGC成为最大亮点—美格智能携手阿加犀推出多感知融合VSLAM解决方案

2024世界移动通信大会盛况空前&#xff0c;AI成为最大亮点。2月28日&#xff0c;美格智能携手阿加犀&#xff0c;将算力模组的硬件优势与AI优化部署技术相结合&#xff0c;在MWC展会现场展示了基于高算力AI模组的多感知融合VSLAM解决方案。这一创新性方案可应用于智能机器人与低…

并查集例题(食物链)C++(Acwing)

代码&#xff1a; #include <iostream>using namespace std;const int N 50010;int n, m; int p[N], d[N];int find(int x) {if(p[x] ! x){int t find(p[x]);d[x] d[p[x]];p[x] t;}return p[x]; }int main() {scanf("%d%d", &n, &m);for(int i 1…

ubuntu+QT+ OpenGL环境搭建和绘图

一&#xff0c;安装OpenGL库 安装OpenGL依赖项&#xff1a;运行sudo apt install libgl1-mesa-glx命令安装OpenGL所需的一些依赖项。 安装OpenGL头文件&#xff1a;运行sudo apt install libgl1-mesa-dev命令来安装OpenGL的头文件。 安装GLUT库&#xff1a;GLUT&#xff08;Ope…

459. 重复的子字符串(力扣LeetCode)

文章目录 459. 重复的子字符串题目描述暴力移动匹配KMP算法 459. 重复的子字符串 题目描述 给定一个非空的字符串 s &#xff0c;检查是否可以通过由它的一个子串重复多次构成。 示例 1: 输入: s “abab” 输出: true 解释: 可由子串 “ab” 重复两次构成。 示例 2: 输入: …

【Simulink系列】——Simulink子系统子系统封装模块库技术

声明&#xff1a;本系列博客参考有关专业书籍&#xff0c;截图均为自己实操&#xff0c;仅供交流学习&#xff01; 引入 前面对于简单的动态系统仿真&#xff0c;可以直接建立模型&#xff0c;然后仿真。但是对于复杂的系统&#xff0c;直接建立系统会显得杂乱无章&#xff0…

文物预防性保护系统方案的需求分析

没有文物保存环境监测&#xff0c;就不能实施有效的文物预防性保护。因此要建立文物预防性保护体系&#xff0c;一定要先有良好的文物状态监测制度,进而进行科学有效的文物保护管理。所以,导入文物预防性保护监测与调控系统,首先就是要针对文物进行全年温度、湿度、光照等关键参…

创建预留跳过ATP检查增强

1、需求背景 业务要求&#xff0c;当创建预留时&#xff0c;根据工厂和库存地点判断是否要进行ATP校验&#xff0c;而不能从物料维度控制ATP校验&#xff0c;因此需要做增强实现。 本文档将实现通过增强在前台MB21和BAPI&#xff1a;BAPI_RESERVATION_CREATE1创建时&#xff…

【大数据】Flink SQL 语法篇(八):集合、Order By、Limit、TopN

Flink SQL 语法篇&#xff08;八&#xff09;&#xff1a;集合、Order By、Limit、TopN 1.集合操作2.Order By、Limit 子句2.1 Order By 子句2.2 Limit 子句 3.TopN 子句 1.集合操作 集合操作支持 Batch / Streaming 任务。 UNION&#xff1a;将集合合并并且去重。UNION ALL&a…

【算法历练】动态规划副本—路径问题

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;宙でおやすみ 1:02━━━━━━️&#x1f49f;──────── 2:45 &#x1f504; ◀️ ⏸ ▶️ ☰ &#…

秋招上岸大厂,分享一下自己的笔记

秋招上岸大厂&#xff0c;说一说自己的经验 网关项目 很多人读了我的《秋招上岸大厂&#xff0c;分享一下自己的经验》这篇文章&#xff0c;来问我&#xff0c;你面试的时候都用什么项目&#xff1f;你的八股都是从哪里学的&#xff1f;你的项目场景是什么样子的呢&#xff1f;…

计算机网络:路由协议

路由协议简介 路由协议是计算机网络中不可或缺的一部分&#xff0c;它们负责确定数据包从源地址到目的地址的最佳路径。想象一下&#xff0c;如果你是一个数据包&#xff0c;路由协议就像是地图或导航工具&#xff0c;指导你如何到达目的地。 目录 路由协议简介 工作原理简化…

web组态软件

1、强大的画面显示web组态功能 2、良好的开放性。 开放性是指组态软件能与多种通信协议互联&#xff0c;支持多种硬件设备&#xff0c;向上能与管理层通信&#xff0c;实现上位机和下位机的双向通信。 3、丰富的功能模块。 web组态提供丰富的控制功能库&#xff0c;满足用户的测…

配置与管理Samba服务器

配置与管理samba服务器 1&#xff0c;作用&#xff1a;可以使用户在异构网络操作系统之间进行文件系统共享 2&#xff0c;**SMB协议&#xff1a;**主要是作为Microsoft网络的通讯协议&#xff1b;一般端口使用为139&#xff0c;445。 3&#xff0c;功能&#xff1a;1&#x…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的活体人脸检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本篇博客详细讲述了如何利用深度学习构建一个活体人脸检测系统&#xff0c;并且提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并进行了与前代算法YOLOv7、YOLOv6、YOLOv5的细致对比&#xff0c;展示了其在图像、视频、实时视频流和批量文件处…

在from子句中使用子查询

目录 查询每个部门的编号、名称、位置、部门人数、平均工资 多表查询分组统计 子查询分组统计 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 为了解释这种查询的作用&#xff0c;下面做一个简单的查询 查询每个部门的编号、名称、…

Qt中tableView控件的使用

tableView使用注意事项 tableView在使用时&#xff0c;从工具栏拖动到底层页面后&#xff0c;右键进行选择如下图所示&#xff1a; 此处需要注意的是&#xff0c;需要去修改属性&#xff0c;从UI上修改属性如下所示&#xff1a; 也可以通过代码修改属性&#xff1a; //将其设…

存内计算技术大幅提升机器学习算法的性能—挑战与解决方案探讨

一.存内计算技术大幅机器学习算法的性能 1.1背景 人工智能技术的迅速发展使人工智能芯片成为备受关注的关键组成部分。在人工智能的构建中&#xff0c;算力是三个支柱之一&#xff0c;包括数据、算法和算力。目前&#xff0c;人工智能芯片的发展主要集中在两个方向&#xff1…

《App备案入门指南》:拯救备案小白,让您不再担心

各大云接入商ICP代备案管理系统均已正式支持App备案。为便于大家快速学习了解App备案的相关知识&#xff0c;创孵猫通过网上搜集和整理为大家准备了一些基础信息与常见问题。 一、App备案流程 App备案流程包括云接入商初审、工信部短信核验、管局终审和备案成功等关键步骤。在…