05.线程

进程有哪些缺陷?

1.创建的代价较高

进程是OS进行资源分配的基本单位,也就是说创建进程是需要分配资源的,所以创建代价很高

2.通信不方便

进程之间要想进行通信必须借助第三方资源(管道、内存映射、消息队列)

线程的优点有哪些?

线程与进行一样,在单核的情情况下都可以并发执行,多核可以并行执行。
但是线程的创建代价没有进程高,一个进程可以创建多个线程,这写线程共享同一份资源。共享同一份资源自然,通信就方便了很多

pthread_create函数

创建线程的函数

int pthread_create(pthread_t *thread,const pthread_attr_t *attr,(void *)( *start_routine)(void *),void *arg)

参一:传出参数,子线程tid
参二:线程的属性(attr)
参三:函数指针,子进程要执行的代码放在这个函数里面
参四:子进程函数的参数
返回值:
成功返回0
失败返回错误号
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
void* thread1(void* arg){sleep(1);printf("thread1 = %lu\n",pthread_self());return NULL;
}int main(int argc, char* argv[])
{pthread_t tid;int ret = pthread_create(&tid,NULL,thread1,NULL);if(ret == -1){perror("pthread_create error:");return -1;}printf("main therad = %lu\n",pthread_self());//%lu是无符号场整形 unsigned long int while(1);return 0;
}

pthread_self函数

获取线程tid的函数

pthread_t pthread_self(void)

返回值和无符号场整形,%lu
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
int a;
void* thread1(void* arg){printf("thread1 tid = %lu\n",pthread_self());while(a!=10){a++;printf("a = %d\n",a);sleep(1);}return NULL;
}
int main(int argc, char* argv[])
{pthread_t tid;int ret = pthread_create(&tid,NULL,thread1,NULL);if(ret != 0){perror("pthread_create error:");return -1;}printf("main thread tid = %lu\n",pthread_self());while(a!=10){a++;printf("a = %d\n",a);sleep(1);}printf("pthread_create ret = %d\n",ret);return 0;
}

终止线程的方法

1.进程结束了,底下的线程肯定都结束了

在主函数执行return

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
int a;
void* thread1(void* arg){while(a!=10){a++;printf("a = %d\n",a);sleep(1);}return NULL;
}
int main(int argc, char* argv[])
{pthread_t tid;pthread_create(&tid,NULL,thread1,NULL);sleep(1);return 0;
}

调用exit()函数

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdlib.h>
int a;
void* thread1(void* arg){while(a!=10){a++;printf("a = %d\n",a);sleep(1);}return NULL;
}
void* thread2(void* arg){sleep(2);exit(-1);return NULL;
}
int main(int argc, char* argv[])
{pthread_t tid;pthread_create(&tid,NULL,thread1,NULL);pthread_create(&tid,NULL,thread2,NULL);while(1);return 0;
}

2.结束当前的线程

在start_rountine函数中执行return

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdlib.h>
int a;
void* thread1(void* arg){while(a!=10){a++;printf("a = %d\n",a);return NULL;printf("1\n");}}
int main(int argc, char* argv[])
{pthread_t tid;pthread_create(&tid,NULL,thread1,NULL);sleep(2);return 0;
}

调用pthread_exit()函数

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdlib.h>
int a;
void func(){printf("This is func!\n");pthread_exit(NULL);
}
void* thread1(void* arg){while(a!=10){a++;printf("a = %d\n",a);func();printf("1\n");}}
int main(int argc, char* argv[])
{pthread_t tid;pthread_create(&tid,NULL,thread1,NULL);sleep(2);return 0;
}

调用pthread_cancel函数

int pthread_cancel(pthread_t thread);
参一为要取消的线程
函数描述:调用该函数之后,会向指定线程发送一个取消请求,然后立即返回,被请求取消的进程需要等到某个取消点(通常为系统调用)
可以调用pthread_testcancel()函数,手动创建取消点
#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdlib.h>
int a;
int stats;void* thread1(void* arg){while(1){if(a == 10){a=0;}a++;pthread_testcancel();}
}
int main(int argc, char* argv[])
{pthread_t tid;pthread_create(&tid,NULL,thread1,NULL);int ret = pthread_cancel(tid);if(ret == 0){printf("cancel sucess!\n");}else{printf("cancel error!\n");}while(1){printf("a = %d\n",a);sleep(1);}return 0;
}

线程的连接和分离

pthread_join函数

函数原型:int pthread_join(pthread_t tid ,void **retval);

函数描述:等待指定线程的结束,然后回收,这种操作被称为连接。未连接的进程会产生僵尸线程

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdlib.h>
int a;void* thread1(void* arg){while(1){if(a == 10){pthread_exit(NULL);}a++;}
}
int main(int argc, char* argv[])
{pthread_t tid;void* res;pthread_create(&tid,NULL,thread1,NULL);pthread_join(tid,&res);printf("res = %s",(char*)res);printf("a = %d\n",a);return 0;
}

有些线程不关心返回状态,只是希望OS能在线程终止的时候自动清理并移出,这时可以调用pthread_detach函数设置线程未分离状态

pthread_detach函数

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdlib.h>
int a;void* thread1(void* arg){while(1){if(a == 10){pthread_exit(NULL);}a++;}
}
void* thread2(void* arg){while(1){if(a == 10){pthread_exit(NULL);}a++;}
}
int main(int argc, char* argv[])
{pthread_t tid1;pthread_t tid2;void* res;pthread_create(&tid1,NULL,thread1,NULL);pthread_create(&tid2,NULL,thread2,NULL);pthread_detach(tid2);pthread_join(tid2,&res);printf("res = %s",(char*)res);printf("a = %d\n",a);return 0;
}

练习

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<stdio.h>
#include<string.h>                                                              
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdlib.h>
const int N=1e6;
int a;
void* thread1(void* arg){for(int i = 1;i <= N; i++){a++;}
}
int main(int argc, char* argv[])
{pthread_t tids[10];//创建10个线程,用tids数组存储tidfor(int i = 0;i < 10; i++){pthread_create(tids+i,NULL,thread1,NULL);}//阻塞等待10个线程都执行结束,打印a的值for(int i = 0;i < 10; i++){pthread_join(tids[i],NULL);}printf("a = %d\n",a);return 0;
}

观察数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线程同步的引入

观察上面的数据,发现10个线程如果同时执行1e6次自增操作,最后结果应该是1e7,但是多次得到的结果确实小于等于1e7,这种情况是不可以接受的,为什么会出现这种问题?

因为线程之间的并发执行的,且a++不是原子操作。
举一个例子,现在线程1和线程2并发执行,它们同时读取了a的数据,读到的都是5,然后对5+1返回结果给a,线程1和线程2同时结束,a的值为6,而不是7,这就出现了问题。出现这个问题的原因是线程之间是共享资源的,同时访问一块内存,有时会造成错误。(保证线程和线程访问同一块空间的时候不出现冲突)
所以得让进程之间商量着来,协同一下步调。

同步

同步分为同步异步的同步和线程同步

同步与异步

提到同步和异步,很难不想到阻塞和非阻塞。

阻塞和非阻塞一半表述进程的状态,具体指的是进程在执行过程中是否遇到阻塞实现(是否被挂起),如果被挂起了就是阻塞状态,没有被挂起就是非阻塞

而同步异步一般指的是系统调用时候是否会阻塞执行

同步函数

同步函数是指在系统调用的过程中,程序会被阻塞,知道系统调用结束返回结果。
特点:
1.阻塞执行
2.可预测,符合传统程序的执行过程

异步函数

异步函数指的是系统调用过程中,程序不会阻塞,继续执行后面的代码。等到系统调用结束之后,内核会通过某种机制(信号或者回调函数等等)通知程序。
特点:
1.非阻塞:不会阻塞等待返回的结果,而是直接执行后面的代码。
2.事件驱动性:当系统调用完成时,内核会通过事件通知应用程序,应用程序需要处理这些事件
3.复杂性:异步编程模型复杂,需要处理多个事件和状态

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Java开发工具Idea的下载与激活

一&#xff0c;官网下载Idea 建议从官网下载&#xff0c;安全、可靠。 1&#xff0c;点击此处进入官网下载 2&#xff0c;进入官网之后点击[Support]&#xff0c;点击浮窗左侧[Download and Install] 3&#xff0c;跳入如下新界面&#xff0c;点击Download进入下载界面 4&am…

汇昌联信数字:拼多多如何开个人店铺?有哪些教程?

在互联网经济飞速发展的当下&#xff0c;电子商务平台如雨后春笋般涌现&#xff0c;其中拼多多以其独特的社交电商模式迅速崛起&#xff0c;吸引了大批商家和个人卖家入驻。如果你正考虑在拼多多开设个人店铺&#xff0c;那么了解开店流程和相关教程就显得尤为重要。以下是关于…

水面垃圾监测识别摄像机

随着城市化进程的加快和旅游业的兴起&#xff0c;水域环境污染问题日益突出&#xff0c;水面垃圾成为环境保护的重要问题。为有效监测和清理水面垃圾&#xff0c;水面垃圾监测识别摄像机应运而生。水面垃圾监测识别摄像机利用高清晰度摄像头和智能识别算法&#xff0c;能够实时…

大语言模型LLM原理篇

大模型席卷全球&#xff0c;彷佛得模型者得天下。对于IT行业来说&#xff0c;以后可能没有各种软件了&#xff0c;只有各种各样的智体&#xff08;Agent&#xff09;调用各种各样的API。在这种大势下&#xff0c;笔者也阅读了很多大模型相关的资料&#xff0c;和很多新手一样&a…

STL-Setmap

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;我们将进入到CSTL 的学习。STL在各各C的头文件中&#xff0c;以源代码的形式出现&#xff0c;不仅要会用&#xff0c;还要了解底层的实现。源码之前&#xff0c;了无秘密。 STL六大组件 Container通过Allocator取得数据储存…

【XR806开发板试用】试用SWD+Jlink调试

XR806开发板&#xff0c;只能使用编写代码&#xff0c;然后通过UART下载&#xff0c;没法在线debug&#xff0c; 效率会差很多&#xff0c;官方没有提供这一方面的资料。 先查CPU&#xff0c; 官方介绍是arm-china的MC1&#xff0c;通过armv8 Architecture refenence manual资料…

利用106短信群发平台能否提升沟通效率?

利用106短信群发平台确实能够显著提升沟通效率&#xff0c;具体体现在以下几个方面&#xff1a; 1.快速传递信息&#xff1a;106短信群发平台能够实现信息的快速传递。一旦设置好发送内容和接收群体&#xff0c;短信便能在瞬间发送至大量用户。这种即时性确保了信息的迅速传达…

Gitlab:从其它项目组里导入一个项目

1.首先获取原项目的http地址 http://ip/projectGroup/ProjectX.git其中&#xff0c;ip 为公司gitlab内网地址。 2.进入目的项目组进行创建 首先&#xff0c;需要拥有一个该组拥有者权限的账号&#xff0c;才能进行后续的操作。 2.1.点击创建项目按钮 2.2.选择导入项目 其中…

11.买卖股票的最佳时机Ⅰ

文章目录 题目简介题目解答解法一&#xff1a;一次遍历代码&#xff1a;复杂度分析&#xff1a; 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 买卖股票的最佳时机面试题Ⅰ 相关的讲解&#xff01;&#x1f600; 题目简介 题目解答 解法一&#xff1a;一次遍历…

怎么让电脑耳机和音响都有声音

电脑耳机音响不能同时用没声音怎么办 一般来说&#xff0c;重新开机后问题能够得到解决。右击“我的电脑”---“属性”---“硬件”---“设备管理器”&#xff0c;打开“声音、视频和游戏控制器”有无问题&#xff0c;即看前面有没有出现黄色的“”。 如果您的 电脑 耳机能正常…

【Linux系统编程】第十六弹---冯诺依曼体系结构与操作系统

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、冯诺依曼体系结构 2、操作系统原理 2.1、什么是操作系统&#xff1f; 2.2、用图解释操作系统 2.3、理解操作系统 总结 …

路由器、交换机和网卡

大家使用VMware安装镜像之后&#xff0c;是不是都会考虑虚拟机的镜像系统怎么连上网的&#xff0c;它的连接方式是什么&#xff0c;它ip是什么&#xff1f; 路由器、交换机和网卡 1.路由器 一般有几个功能&#xff0c;第一个是网关、第二个是扩展有线网络端口、第三个是WiFi功…

在做题中学习(55):一维前缀和模板

【模板】前缀和_牛客题霸_牛客网 (nowcoder.com) 题目解释&#xff1a; 注意&#xff1a;下标从1开始的。 l 和 r就是对这n个整数去取一个区间&#xff0c;例如示例一&#xff1a; (1,2) 区间 就是算出1 2 4 中 1&#xff0c;2下标对应值的和&#xff0c;12 3 同理,(2,3) …

SHAP分析+立方样条拟合的展示可能的交互作用

SHAP分析立方样条的拟合展示可能的交互作用 SHAP分析的另一个特点就是对交互作用的分析&#xff0c;计算交互作用的SHAP值&#xff0c;绘制相关的交互作用图表&#xff0c;但是仅局限于xgboost模型&#xff0c;其它的模型不能单独计算相互作用的SHAP值&#xff0c;也就不能绘制…

React 第二十九章 React 和 Vue 描述页面的区别

面试题&#xff1a;React 和 Vue 是如何描述 UI 界面的&#xff1f;有一些什么样的区别&#xff1f; 标准且浅显的回答&#xff1a; React 中使用的是 JSX&#xff0c;Vue 中使用的是模板来描述界面 前端领域经过长期的发展&#xff0c;目前有两种主流的描述 UI 的方案&#xf…

读写备份寄存器BKP与实时时钟RTC

文章目录 读写备份寄存器接线图代码 RTC实时时钟接线图代码 读写备份寄存器 接线图 即接个3.3v的电源到VBT引脚 代码 代码效果&#xff1a;第一次写入备份寄存器&#xff0c;下载程序后再注释掉&#xff0c;再进行下载&#xff0c;之前写入的数据还会保存在备份寄存器中&am…

QQ无人直播秘籍:24小时自动化短剧,边睡边赚,月入过万实战分享!

在如今经济大环境如此糟糕的时代&#xff0c;寻找一种简单、有效的方式来实现日入1000的梦想成为了许多人的追求。而QQ短剧24小时无人直播项目&#xff0c;则是一个备受瞩目的赚钱机会。借助腾讯官方流量扶持&#xff0c;这个项目不仅能够让创业者轻松入门&#xff0c;还能够实…

新火种AI|正面硬刚OpenAI与谷歌?微软竟然偷偷自研出5000亿参数大模型!

在AI领域&#xff0c;微软公司一直以其独到的创新性和前瞻性而闻名。也正因此&#xff0c;它抢先在AI赛道嗅到商机&#xff0c;并极具预判性的投资了OpenAI&#xff0c;使其成为自己在AI赛道上的最强助力。不过&#xff0c;微软的野心不止于此。 根据The Information 5月6日的…

光耦推荐—高速风筒方案中用到哪些光耦型号

高速风筒是现代生活中常见的电器设备&#xff0c;广泛应用于家庭、商业和工业领域&#xff1b;光耦是一种能够将输入信号转换成输出信号的元器件&#xff0c;其作用在于将电气信号转换成光信号&#xff0c;从而实现电路的隔离和保护&#xff1b;采用光耦可实现对风机转速和温度…

品牌控价前要先了解目标

对渠道中出现的低价链接、窜货链接进行治理的过程&#xff0c;就叫做控价&#xff0c;控价的最终目的是为使这些低价链接下架或者改价&#xff0c;但不是所有品牌都只做打击&#xff0c;便能管控好渠道的&#xff0c;也就是说&#xff0c;控价的方法不能只依靠治理&#xff0c;…