linux学习:线程

目录

线程api

创建一条新线程

获取、设置线程的分离属性

获取、设置线程是否继承创建者的调度策略

获取、设置线程的调度策略

获取、设置线程静态优先级  获取、设置线程动态优先级

获取、设置线程栈大小、警戒区大小

退出线程

接合指定线程

给指定线程发送一个取消请求

获取、设置线程的取消状态和取消类型

压栈、或弹栈线程的取消处理例程

例子

创建一条线程,他的执行例程,线程退出,并被主线程接合

产生一个包含“分离”状态的属性变量,用此变量产生线程,使该线程退出后不会变成僵尸

取消一条线程,及该线程如何正确地处理该取消请求


线程api

创建一条新线程

注意

  • 线程例程指的是:如果线程创建成功,那么该线程会立即去执行的函数
  • POSIX 线程库的所有 API 对返回值的处理原则都是一致的:成功返回 0,失败返 回错误码 errno
  • 线程属性如果为 NULL,则会创建一个标准属性的线程,线程的属性非常多

线程属性变量api

以上 API 都是针对线程属性操作的,所谓线程属性是类型为 pthread_attr_t 的 变量,设置一个线程的属性时,通过以上相关的函数接口,将需要的属性添加到该类型 变量里面,再通过 pthread_create( )的第二个参数来创建相应属性的线程

注意

  • 定义线程属性变量,并且使用 pthread_attr_init( )初始化。
  • 使用 pthread_attr_setXXX( )来设置相关的属性
  • 使用该线程属性变量创建相应的线程
  • 使用 pthread_attr_destroy( )销毁该线程属性变量

获取、设置线程的分离属性

一条线程如果是可接合的,意味着这条线程在退出时不会自动释放自身资源,而会成为 僵尸线程,同时意味着该线程的退出值可以被其他线程获取。因此,如果不需要某条线程的 退出值的话,那么最好将线程设置为分离状态,以保证该线程不会成为僵尸线程

获取、设置线程是否继承创建者的调度策略

当需要给一个线程设置调度方面的属性时,必须先将线程的 inheritsched 设置为 PTHREAD_EXPLICIT_SCHED

获取、设置线程的调度策略

注意

  • 当线程的调度策略为 SCHED_FIFO 时,其静态优先级(static priority)必须设 置为 1-99,这将意味着一旦这种线程处于就绪态时,他能立即抢占任何静态优先级为 0 的 普通线程。采用 SCHED_FIFO 调度策略的线程还遵循以下规则:
    • A) 当他处于就绪态时,就会被放入其所在优先级队列的队尾位置。
    • B) 当被更高优先级的线程抢占后,他会被放入其所在优先级队列的队头位置,当 所有优先级比他高的线程不再运行后,他就恢复运行。
    • C) 当他调用 sched_yield( )后,他会被放入其所在优先级队列的队尾的位置。 总的来讲,一个具有 SCHED_FIFO 调度策略的线程会一直运行直到发送 I/O 请求, 或者被更高优先级线程抢占,或者调用 sched_yield( )主动让出 CPU
  • 当线程的调度策略为 SCHED_RR 时,情况跟 SCHED_FIFO 是一样的,区别在于: 每一个 SHCED_RR 策略下的线程都将会被分配一个额度的时间片,当时间片耗光时,他 会被放入其所在优先级队列的队尾的位置。可以用 sched_rr_get_interval( )来获得时间 片的具体数值
  • 当线程的调度策略为 SCHED_OTHER 时,其静态优先级(static priority)必须 设置为 0。该调度策略是 Linux 系统调度的默认策略,处于 0 优先级别的这些线程按照所 谓的动态优先级被调度,而动态优先级起始于线程的 nice 值,且每当一个线程已处于就绪 态但被调度器调度无视时,其动态优先级会自动增加一个单位,这样能保证这些线程竞争 CPU 的公平性

获取、设置线程静态优先级  获取、设置线程动态优先级

注意

  • 静态优先级是一个定义如下的结构体
    struct sched_param
    {int sched_priority;
    };

    可见静态优先级就是一个只有一个整型数据的结构体,这个整型数值介于0到99之间, 0 级线程被称为非实时的普通线程,他们之间的调度凭借所谓的动态优先级来博弈。而 1-99 级线程被称为实时线程,他们之间的调度凭借他们不同级别的静态优先级和不同的调度策略 (如果他们的静态优先级一样的话)来博弈

  • 线程的静态优先级(static priority)之所以被称为“静态”,是因为只要你不强行使用相关函数修改他,他不会随着线程的执行而发生改变,静态优先级决定了实时线程的基本调度次序,如果他们的静态优先级一样,那么调度策略再为调度器提供进一步的调度依据
  • 线程的动态优先级(dynamic prioriy)是非实时的普通线程独有的概念,之所以 被称为“动态”,是因为它会随着线程的运行,根据线程的表现而发生改变,具体来讲是— —如果一条线程是“CPU 消耗型”的,比如视频解码算法,这类线程只要一运行就黏住 CPU 不放,这样的线程的动态优先级会被慢慢地降级,这符合我们的预期,因为这类线程不需要 很高的响应速度,你只要保证一定的执行时间片就可以了。相反,另一类线程被称为“IO 消耗型”,比如编辑器,这类线程绝大部分的时间都在睡眠,调度器发现每次调度他他都毅 然决然地放弃了,将宝贵的 CPU 让给了其他线程,了不起是个大好人,因此会慢慢地提高 他的动态优先级,使得这类线程在同等的非实时普通线程中,有越来越高的响应速度,表现 出更好的交互性能,这也正是我们想要的结果

获取、设置线程栈大小、警戒区大小

注意

  • 线程栈是非常重要的资源,用以存放诸如函数形参、局部变量、线程切换现场寄存器数 据等等,一个多线程进程的栈空间,包含了所有线程各自的栈

退出线程

线程跟进程类似,在缺省的状态下退出之后,会变成僵尸线程,并且保留退出值。其他线程可以通过相关 API 接合该线程——使其资源被系统回收,如果愿意的话还可以顺便获取其退出值

接合指定线程

注意

  • 如果线程退出时没有退出值,那么 retval 可以指定为 NULL
  • pthread_join( )指定的线程如果尚在运行,那么他将会阻塞等待
  • pthread_tryjoin_np( )指定的线程如果尚在运行,那么他将会立即出错返回

给指定线程发送一个取消请求

另外,或许在某个时刻不能等某个线程“自然死亡”,而需要勒令其马上结束,此时可 以给线程发送一个取消请求,让其中断执行而退出

而当线程收到一个取消请求时,他将会如何表现取决于两个东西:一是当前的取消状态, 二是当前的取消类型。线程的取消状态很简单——分别是 PTHREAD_CANCEL_ENABLE 和 PTHREAD_CANCEL_DISABLE,前者是缺省的,代表线程可以接受取消请求,后者代 表关闭取消请求,不对其响应。

而在线程接受取消请求的情况下,如何停下来又取决于两种不同的响应取消请求的策略 ——延时响应和立即响应,当采取延时策略时,线程并不会立即退出,而是要遇到所谓的“取 消点”之后,才退出。而“取消点”,指的是一系列指定的函数。

获取、设置线程的取消状态和取消类型

压栈、或弹栈线程的取消处理例程

由于线程任何时刻都有可能持有诸如互斥锁、信号量等资源,一旦被取消很有可能导致别的线程出现死锁,因此如果一条线程的确可能被取消,那么在被取消之前必须使用以下 API 来为将来可能出现的取消请求注册“处理例程”,让这些例程自动释放持有的资源

例子

创建一条线程,他的执行例程,线程退出,并被主线程接合

1 #include <stdio.h>
2 #include <pthread.h>
3 // 线程函数
4 void *routine(void *arg)
5 {
6     char *s = (char *)arg; // 将创建线程传进来的参数转换为其原本类型
7     printf("argument: %s", s);
8
9     sleep(1); // 睡眠 1 秒钟后退出
10    pthread_exit("Bye-Bye!\n");// 退出传出的值
11 }
12
13 int main(int argc, char **argv)
14 {
15     // 创建线程,指定其执行例程为 routine( )并将字符串传递给他
16     pthread_t tid;
17     pthread_create(&tid, NULL, routine, (void *)"testing string\n");
18
19     // 阻塞等待指定线程退出,并获取其退出值
20     void *p;
21     pthread_join(tid, &p);
22     // 打印其退出值
23     printf("exit value: %s", (char *)p);
24
25     return 0;
26 }

产生一个包含“分离”状态的属性变量,用此变量产生线程,使该线程退出后不会变成僵尸

1 #include <stdio.h>
2 #include <pthread.h>
3 // 线程函数
4 void *routine(void *arg)
5 {
6     pthread_exit(NULL); // 由于已分离,该线程退出后会自动释放资源
7 }
8
9 int main(int argc, char **argv)
10 {
11     // 初始化一个属性变量,并将分离属性加入该变量
12     pthread_attr_t attr;// 创建一个属性变量
13     pthread_attr_init(&attr);// 初始化线程属性变量 attr
14     pthread_attr_setdetachstate(&attr, 
15                PTHREAD_CREATE_DETACHED);// 赋值给属性变量
16
17     // 用该属性变量产生一条新线程
18     pthread_t tid;
19     pthread_create(&tid, &attr, routine, NULL);
20
21     // 主线程暂停,否则 return 语句会导致整个进程退出
22     pause();
23     return 0;
24 }

取消一条线程,及该线程如何正确地处理该取消请求

1 #include <stdio.h>
2 #include <pthread.h>
3
4 pthread_mutex_t m;// 声明了一个互斥锁 m
5 // 线程退出的时候会触发的解锁互斥锁函数
6 void handler(void *arg)
7 {
8     pthread_mutex_unlock(&m); // 解锁
9 }
10 // 线程函数
11 void *routine(void *arg)
12 {
13     // 加锁前,将 handler函数压入线程取消处理例程的栈中,以防中途被取消
14     pthread_cleanup_push(handler, NULL);
15     pthread_mutex_lock(&m);//上锁
16
17     printf("[%u][%s]: abtained the mutex.\n", 
18                 (unsigned)pthread_self(), 
19                               __FUNCTION__);
20     sleep(10); // 在此线程睡眠期间如果收到取消请求,handler 将被执行
21
22     
23     pthread_mutex_unlock(&m);// 解锁
24     pthread_cleanup_pop(0);// 将 handler函数从栈中弹出,但不执行它
25
26     pthread_exit(NULL);// 退出
27 }
28
29 int main(int argc, char **argv)
30 {
31     pthread_mutex_init(&m, NULL);// 初始化了互斥锁 m
32
33     pthread_t tid;// 新线程
34     pthread_create(&tid, NULL, routine, NULL);// 线程执行函数
35
36     // 等待 1 秒钟之后,向子线程发送一个取消请求
37     sleep(1);
38     pthread_cancel(tid);
39
40     // 此时子线程虽被取消了,但被 handler 自动释放,因此主线程可加锁
41     pthread_mutex_lock(&m);
42     printf("[%u][%s]: abtained the mutex.\n", 
43             (unsigned)pthread_self(), 
44             __FUNCTION__);
45     pthread_mutex_unlock(&m);// 解锁46
47     return 0;
48 }

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

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

相关文章

鸿蒙开发语言_ArkTS开发语言体验_TypeScript语言环境搭建_TS声明和数据类型---HarmonyOS4.0+鸿蒙NEXT工作笔记003

可以看到我们新建的这个项目,有个 @State message: String =Hello ArkTS 这个就是定义了一个变量,可以看到 message是变量名,String是变量类型. 然后我们可以看看它的结构可以看到 build() 下面有个Row,然后再下面有个Column方法,然后,里面就是具体的内容了,首先就是显示了一…

二、OSPF协议基础

基于SPF算法&#xff08;Dijkstra算法&#xff09;的链路状态路由协议OSPF&#xff08;Open Shortest Path First&#xff0c;开放式最短路径优先&#xff09; 目录 1.RIP在大型网络中部署所面临的问题 2.Router ID 3.OSPF的报文 4.OSPF邻居建立过程 5.OSPF报文的确认机制…

在 Linux 上把 Vim 配置为默认编辑器

目录 ⛳️推荐 在 Linux 命令行中编辑 将 Vim 设置为其他程序的默认值 在 Alpine 中编辑电子邮件 总结 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 我使用 Linux 大概有…

3D MINS 多模态影像导航系统

3D MINS多模态影像导航系统&#xff08;Multimodal Image Navigation System&#xff09;是SunyaTech研发的建立在DICOM&#xff08;Digital Imaging and Communications in Medicine&#xff09;图像基础之上的多模态影像导航系统&#xff0c;集二维影像PACS管理、三维影像层级…

Python函数小知识

目录 一、函数的定义和调用 二、函数参数 三、函数作用域 四、递归函数和匿名函数 一、函数的定义和调用 def 函数名(参数): 自定义函数可以分为有参函数和无参函数 。 函数的作用&#xff1a; 在Python中定义函数可以提高代码的复用率&#xff0c;避免重复的代码&#xff0c;…

Elastic 网络爬虫:为你的网站添加搜索功能

作者&#xff1a;来自 Elastic Lionel Palacin 为了演示如何使用 Elastic 网络爬虫&#xff0c;我们将以一个具体的网站为例&#xff0c;讲解如何在该网站上添加搜索功能。我们将探讨发现网站的方法&#xff0c;并利用 Elastic 网络爬虫提供的功能&#xff0c;以最佳方式准备待…

30 OpenCV 点多边形测试

文章目录 点多边形测试pointPolygonTest示例 点多边形测试 pointPolygonTest pointPolygonTest( InputArray contour,// 输入的轮廓 Point2f pt, // 测试点 bool measureDist // 是否返回距离值&#xff0c;如果是false&#xff0c;1表示在内面&#xff0c;0表示在边界上&a…

Spring Boot中判断轨迹数据是否经过设置的打卡点,且在PGSQL中把点拼接成线,判断某个点是否在线上或在线的50米范围内

问题描述 轨迹数据判断是否经过打卡点&#xff0c;轨迹数据太多&#xff0c;循环判断的话非常消耗内存。解决办法只需要把所有轨迹数据点拼成了一条线&#xff0c;然后只需要循环打卡点即可&#xff0c;打卡点不多&#xff0c;一般不会超过100个&#xff0c;如果多的话&#x…

“一个有趣的C语言代码”分析

“一个有趣的C语言代码” 一个有趣的C语言代码-流浪的海豚-ChinaUnix博客 #include <stdio.h> int print() {printf("hello world!\n");return 0; } int main(void) {long base[0];long* result base3;*(result1) *result;*result (long)print;return 0; …

ARM DMIPS算力说明

ARM DMIPS算力说明 ARM算力参考官网地址 https://en.wikipedia.org/wiki/List_of_ARM_processors Product familyARM architectureProcessorFeatureCache (I / D), MMUTypical MIPS MHzReferenceARM1ARMv1ARM1First implementationNoneARM2ARMv2ARM2ARMv2 added the MUL (mu…

无人零售与传统便利店的竞争优势

无人零售与传统便利店的竞争优势 成本控制 • 无人零售 显著降低了人力成本&#xff0c;无需支付店员薪资和相关福利&#xff0c;且通过智能化管理减少能源消耗与维护费用&#xff0c;尤其在高租金和高人流区域效益突出。 • 传统便利店 则承担较高的人员开支&#xff0c;…

Nginx 四层和七层代理区别、配置

四层&#xff1a;通过报文中的目标地址和端口&#xff0c;加上负载均衡设备设置的服务器选择方式&#xff0c;决定最终选择的内部服务器&#xff0c;使用tcp、udp协议。 七层&#xff1a;"内容交换"&#xff0c;通过报文中真正有意义的应用层内容&#xff0c;加上负…

GPT的全面历史和演变:从GPT-1到GPT-4

人工智能新篇章&#xff1a;GPT-4与人类互动的未来&#xff01; 本文探讨了生成式预训练 Transformer (GPT) 的显着演变&#xff0c;提供了从开创性的 GPT-1 到复杂的 GPT-4 的旅程。 每次迭代都标志着重大的技术飞跃&#xff0c;深刻影响人工智能领域以及我们与技术的互动。 我…

MIS微调SAM模型实时交互UI界面

前言 SAM模型的基本介绍可见SAM&#xff08;Segment Anything Model&#xff09;大模型使用--point prompt_sam大模型-CSDN博客 针对Meta团队去年发布的SAM大模型在医学图像分割领域表现性能较差的情况&#xff0c;笔者收集了一些MIS领域的数据集对SAM的架构进行fine tune&am…

akSmart大带宽服务器基础配置科普

在数字化时代&#xff0c;服务器的性能和网络带宽成为业务发展的关键因素。RakSmart作为知名的服务器提供商&#xff0c;其大带宽服务器备受用户青睐。那么&#xff0c;RakSmart大带宽服务器的基础配置究竟有哪些呢?本文将为您揭开这一神秘面纱。 首先&#xff0c;我们来看看R…

信创需求激增,国产服务器操作系统赋能数字化转型

信创&#xff0c;即信息技术应用创新&#xff0c;是指在关键领域和环节推进信息技术的自主创新&#xff0c;构建安全可控的信息技术体系。随着数字化转型的加速&#xff0c;信创需求激增&#xff0c;国产服务器操作系统在其中扮演着至关重要的角色。国产服务器操作系统如何赋能…

爬虫入门——Request请求

目录 前言 一、Requests是什么&#xff1f; 二、使用步骤 1.引入库 2.请求 3.响应 三.总结 前言 上一篇爬虫我们已经提及到了urllib库的使用&#xff0c;为了方便大家的使用过程&#xff0c;这里为大家介绍新的库来实现请求获取响应的库。 一、Requests是什么&#xff1…

发布 Chrome/Edge浏览器extension扩展到应用商店

Chrom Extension发布流程 创建和发布自定义 Chrome 应用和扩展程序&#xff1a;https://support.google.com/chrome/a/answer/2714278?hlzh-Hans 在 Chrome 应用商店中发布&#xff1a;https://developer.chrome.com/docs/webstore/publish?hlzh-cn 注册开发者帐号&#…

Java 实际项目开发之最少必要知识汇总

一、面向过程和面向对象 程序设计语言分为面向过程和面向对象 对于面向过程&#xff0c;强调的是过程&#xff0c;关心的是我去做 对于面向对象&#xff0c;强调的是对象&#xff08;万物皆对象&#xff09;&#xff0c;更关心的是我该让谁去做&#xff0c;这里的谁指的就是对象…

Hadoop+Spark大数据技术(微课版)曾国荪、曹洁版思维导图第四次作业 (第4章 HBase分布式DB)

1.简述Hbase的特点及与传统关系数据库的区别 HBase与传统关系数据库的区别 &#xff08;1&#xff09;数据类型 关系数据库具有丰富的数据类型&#xff0c;如字符串型、数值型、日期型、二进制型等。HBase只有字符串数据类型&#xff0c;数据的实际类型都是交由用户自己编写程序…