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

线程相关函数接口:

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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

低带待机和静音功能的低压立体声耳机放大电路,电源纹波抑制比高,采用SSOP10封装——D7000

D7000低电压立体声手机功放电路。 主要特点&#xff1a; ● 静态电流低 ● 电源纹波抑制比高 ● 工作电压低 ● 内置节电模式开关和静噪开关 ● 外接元件少所需外围元件少 ● 封装形式: SSOP10 应用&#xff1a; ● 便携式视盘播放器(DISCMAN) ● 便携式迷你播放器(MD) ● D…

Kubernetes剖析

Kubernetes剖析 前言 ​ 容器技术这样一个新生事物&#xff0c;完全重塑了整个云计算市场的形态。它不仅催生出了一批年轻有为的容器技术人&#xff0c;更培育出了一个具有相当规模的开源基础设施技术市场。 ​ 在这个市场里&#xff0c;不仅有 Google、Microsoft 等技术巨擘…

2024022802-信息安全(五)——消息认证、数字签名及PGP

消息认证 消息认证 (Message Authentication)&#xff1a;是一个证实收到的消息来自可信的源点且未被篡改的过程。 鉴别的目的 鉴别的主要目的有二&#xff1a; 第一&#xff0c;验证信息的发送者是真正的&#xff0c;而不是冒充的&#xff0c;此为信源识别&#xff1b; 第二…

XXE 漏洞简单研究

近期在做个基础的 web 常见漏洞的 ppt&#xff0c;主要参考 OWASP TOP 10 2017RC2&#xff0c;此版本中增加了 XXE 攻击&#xff0c;所以自己简单的研究下 XXE 攻击。XXE&#xff08;XML External Entity&#xff09;XML 外部实体&#xff0c;当前端和后端通信数据采用 xml&…

高级语言期末2011级A卷(软件学院)

1.编写函数&#xff0c;判定正整数m和n&#xff08;均至少为2&#xff09;是否满足&#xff1a;数m为数n可分解的最小质因数&#xff08;数n可分解的最小质因数为整除n的最小质数&#xff09; 提示&#xff1a;判定m为质数且m是n的最小因数 #include <stdio.h> #include…

5G网络频谱划分与应用

频率越大&#xff0c;波长越短。补充&#xff1a;微波频段&#xff1a;300MHZ~3000GHZ。 5G网络工作频带与带宽配置 &#xff08;1&#xff09; FR1:410MHZ~7125MHZ。 FR2&#xff1a;24250MHZ~52600MHZ 注&#xff1a;早期将6GHZ已下频段作为FR1&#xff0c;但是最新的频段…

基于Springboot的计算机知识竞赛网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的计算机知识竞赛网站&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

Python爬虫获取淘宝商品详情页数据|实现自动化采集商品信息

要实现自动化采集淘宝商品详情页数据&#xff0c;可以使用Python的第三方库如requests和BeautifulSoup。以下是一个简单的示例&#xff1a; Taobao.item_get-获得淘宝商品详情数据接口返回值说明 1.请求方式:HTTP POST &#xff1b;复制Taobaoapi2014获取APISDK文件。 2.请求…

【GO开发工程师】grpc进阶#golang

【GO开发工程师】grpc进阶#golang 推荐个人主页&#xff1a;席万里的个人空间 文章目录 【GO开发工程师】grpc进阶#golang1、protobuf2、grpc2.1、gRPC 的 Metadata机制2.2、grpc拦截器 1、protobuf syntax "proto3"; // 指定使用的 protobuf 版本为 proto3 import…

牛客周赛 Round 34(A,B,C,D,E,F,G)

把这场忘了。。官方也迟迟不发题解 比赛链接 出题人题解 A 小红的字符串生成 思路&#xff1a; 枚举四种字符串打印出来即可&#xff0c;为了防止重复可以用set先去一下重。 code&#xff1a; #include <iostream> #include <cstdio> #include <cstring&g…

【服务发现--ingress】

1、ingress介绍 Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。 Ingress 是对集群中服务的外部访问进行管理的 API 对象&#xff0c;典型的访问方式是 HTTP。 Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟…

【飞桨EasyDL】飞桨EasyDL发布的模型转换onnx(附工程代码)

一个愿意伫立在巨人肩膀上的农民...... 一、paddle转onnx转rknn环境搭建 paddle转onnx和onnx转rknn两个环境可以分开搭建&#xff0c;也可以搭建在一起。这里选择分开搭建&#xff0c;先搭建paddle转onnx。 1.1、创建环境 选择python3.8.13包进行创建环境 conda create --nam…