首页 > 编程语言 >系统编程-多线程1

系统编程-多线程1

时间:2024-08-28 19:53:56浏览次数:6  
标签:函数 -- void 编程 系统 线程 pthread 进程 多线程

多线程1

目录

多线程1

引入

认识线程

1、线程的概念

2、线程的优缺点

3、进程和线程的区别和联系

4、什么时候选进程,什么时候选线程?

线程相关函数

1、创建线程

2、线程的退出函数

3、阻塞等待线程退出 并回收资源

4、获取自身线程号的函数

5、主动取消一个线程

6、注册线程退出清理函数

7、线程间通信

补充


引入

-- 进程是系统中程序执行和资源分配的基本单位。每个进程有自己的数据段、代码段和堆栈段。由前面的学习 可知,实现进程间通信需要借助 Linux 操作系统中的专门通信机制,这些通信机制将占用大量的系统资源,线程间可以共享数据,更容易通信,因此引入了线程的概念。

-- 线程是在并发执行的多道执行路径,是一个更加接近于执行体的概念,拥有独立的执行序列,是进程的基本调度单元,每个进程至少都有一个main 线程。它与同进程中的其他线程共享进程空间{ 堆 代码 数据 文件描 述符 信号等},只拥有自己的栈空间,大大减少了资源的开销。

-- Linux 的线程是通过用户级的函数库实现的,一般采用 pthread 线程库实现线程的访问和控制。它用第三方posix 标准的 pthread,具有良好的可移植性。编译的时候要在后面加上 – lpthread。

认识线程

1、线程的概念

  • 线程是一个轻量级的进程,多个线程运行在同一个进程空间里面。多个线程共享一个进程资源。

-- 进程有独立的地址空间,线程没有单独的地址空间。(同一进程内的线程共享进程的地址空间)

线程的特点类似于进程
1 异步性
2 并发性
3 动态性
4 独立性
进程能干的事情 线程都可以干
线程和进程可以达到同样的效果

-- 主函数 (main)就是一个线程

2、线程的优缺点

  • 优点:占用系统的资源少,通信简单

  • 缺点:调度没有进程方便,对资源的操作不安全

3、进程和线程的区别和联系

-- 区别

第一:和进程相比,它是一种非常“节俭” 的多任务操作方式。在 linux 系统中建立一个新的进程必须分配给它独立的地址空间, 建立众多的数据表来维护它的代码段、堆栈段和数据段等。
而运行于同一个进程的多个线程,它们之间使用相同的地址空间,而且线程间彼此切换所需的时间也远小于进程间切换的时间。
第二:线程间方便的通信机制。对于不同进程,它们有独立的数据空间 数据的交互只能使用进程通信的方式,这种方式费时,而且不方便。
但是同一个进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其他线程所有,快捷,方便。

-- 联系

线程和进程在使用上各有优缺点:线程执行开销小,占用的 CPU 资源少,线程之间的切换快,但不利于资源的管理和保护;
而进程正相反。从可移植性来讲,多进程的可移植性要好些。要注意的是由于线程共享了进程的资源和地址空间,因此,任何线程对系统资源的操作都会给其他线程带来影响,同时编写多线程程序,最复杂的事情是处理好各线程对共享资源的访问控制。

alt text

4、什么时候选进程,什么时候选线程?

  • 1)需要频繁创建销毁的优先用线程,因为对进程来说创建和销毁一个进程代价是很大的。

  • 2)  线程的切换速度快,所以在需要大量计算,切换频繁时用线程,还有耗时的操作使用线程可提高应用程序的响应

  • 3)强相关的处理用线程,弱相关的处理用进程
    (两件毫不相关的事情用进程,两个事件有很多要联系的用线程。)

  • 4)因为对CPU系统的效率使用上线程更占优,所以可能要发展到多机分布的用进程,多核分布用线程;

  • 5)需要更稳定安全时,适合选择进程;需要速度时,选择线程更好。

线程相关函数

-- 在 linux 下线程操作使用的是别人的函数库来实现的 编译代码的时候需要添加 -lpthread

  • gcc xxx.c -lpthread

1、创建线程

-- 函数头文件

  • #include <pthread.h>

-- 函数原型

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

-- 函数作用:

  • 创建一个新线程

-- 函数参数

  • thread:线程标识符,是一个指向线程标识符指针

线程号 ,定义一个pthread_t id; 填写&id即可。

  • attr:创建出来线程的属性,一般用默认属性,NULL
  • start_routine:线程运行函数的起始地址

void * (*start_routine) (void *):函数指针
创建线程出来之后 线程会去运行该函数
例如:void * func(void *a)
在该参数中填写 func 即可

  • arg:传递给线程运行函数的参数

-- 返回值

  • 成功:0
  • 失败:-1

-- 线程共享全局区域,一个线程的非正常死亡会引起进程的死亡

alt text

2、线程的退出函数

-- 函数头文件

  • #include <pthread.h>

-- 函数原型

  • void pthread_exit(void *retval);

-- 函数作用:

  • 退出当前线程

-- 函数参数

  • retval:线程的返回值,通常传 NULL

-- 返回值

3、阻塞等待线程退出 并回收资源

-- 函数头文件

  • #include <pthread.h>

-- 函数原型

  • int pthread_join(pthread_t thread, void **retval);

-- 函数作用:

  • 阻塞等待指定的线程退出 并回收资源

-- 函数参数

  • thread:线程标识符,要等待的线程号
  • retval:用于获取线程退出的返回值

-- 返回值

  • 成功:0
  • 失败:-1

alt text

-- 获取返回值的办法过于繁琐,其实可以直接创建一个全局变量,把值赋值成8即可。

alt text

4、获取自身线程号的函数

-- 函数头文件

  • #include <pthread.h>

-- 函数原型

  • pthread_t pthread_self(void)

-- 函数的作用:

  • 获取当前线程的线程号 因为有些函数需要线程号进行传递参数

-- 函数的返回值:

  • 不会失败 返回线程的线程号

alt text

5、主动取消一个线程

-- 函数的头文件

  • #include <pthread.h>

-- 函数原型

  • int pthread_cancel(pthread_t thread)

-- 函数的作用:

  • 调用该函数可以主动的取消一个正在运行的线程

-- 函数的参数:

  • thread:要取消的线程 id

-- 函数的返回值:

  • 成功返回 0
  • 失败返回 非零

alt text

6、注册线程退出清理函数

-- 函数头文件

  • #include <pthread.h>

-- 函数原型

  • void pthread_cleanup_push(void (*routine)(void *),void *arg);
  • void pthread_cleanup_pop(int execute);

-- 函数的作用:

  • 当想让线程退出时自动的执行某个函数时使用

-- 函数的参数:

  • push 函数:void (*routine)(void *):函数指针 指向退出时要调用的函数
  • void *arg:退出时调用的函数的传入的参数
  • pop 函数:
    execute为0,不执行退出清理函数,execute为1 执行退出清理函数

-- push 函数中注册的函数什么时候会被调用

  • 1 当运行到 pop 函数时 该函数参数的参数不为 0 时
  • 2 当未运行到 pop 函数时 遇到 pthread_exit 函数时
  • 3 当未运行到 pop 函数时 被 pthread_cancel 函数取消时

-- !!!!!!!!!!! pop和push函数必须成对出现,否则会报错,
(1)push和pop必须定义在一个{}里
(2)push和pop之间的内容不能是死循环,要能到达pop函数

alt text

alt text


-- 

alt text

-- 

alt text

-- 

alt text

7、线程间通信

  • 1 使用全局变量进行线程间的通信
  • 2 发信号
#include <signal.h>     
int pthread_kill(pthread_t thread, int sig)     

-- 使用方法跟进程间的信号一模一样没有区别

alt text

-- 也可以使用信号改造函数

alt text

补充

alt text

标签:函数,--,void,编程,系统,线程,pthread,进程,多线程
From: https://blog.csdn.net/m0_71813740/article/details/141648381

相关文章

  • 系统编程-消息队列
    消息队列目录消息队列引入一、消息队列的特点二、使用指令查看消息队列三、使用消息队列进行通信的步骤1、获取键值2、创建或获取消息队列id3、使用消息队列进行数据的传输4、msgrcv--从消息队列中读取数据5、消息队列的多种操作函数引入--进程间通信(IPC)......
  • 系统编程-共享内存
    共享内存目录共享内存引入一、使用指令查看共享内存二、使用共享内存进行通信的步骤1、获取键值2、创建或获取共享内存id3、映射共享内存到进程的地址空间4、进行数据的写入和读取        --memcpy5、对“块”进行赋值操作5、解除映射6、共享内存的多......
  • 重头开始嵌入式第二十九天(Linux系统编程 网络通信 tcp)
    目录1.常见网络模型1.bs2.p2p3.cs2.网络编程之TCP(传输控制协议)1.TCP模型2.服务器端:1.socket();2、bind();3、listen();4、accept();5、接受函数:/发送函数:6、close()  ===>关闭指定的套接字id;3.客户端:1.connect();2、send()3、客户端信息获取4、客户端的信息bin......
  • java+vue计算机毕设物业信息管理系统【源码+开题+论文】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着城市化进程的加速和居民生活水平的提高,物业管理作为现代社区管理的重要组成部分,其复杂性和重要性日益凸显。传统的人工物业管理方式已难以满足当......
  • java+vue计算机毕设图书馆自习室管理系统【源码+开题+论文】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着高等教育的普及与知识经济的蓬勃发展,图书馆作为知识传播与学术交流的重要场所,其服务功能日益多元化与精细化。近年来,图书馆自习室因其安静的学习......
  • 单例模式 lock 多线程 双重检查锁定机制
    单例模式单例模式publicclassSingleton{//定义一个静态变量来保存类的实例privatestaticSingletonuniqueInstance;//定义一个标识确保线程同步privatestaticreadonlyobjectlocker=newobject();//定义私有构造函数,使外界不能创建该类......
  • 基于springboot+vue.js的超市购物系统附带文章源码部署视频讲解等
    文章目录前言详细视频演示具体实现截图核心技术介绍后端框架SpringBoot前端框架Vue持久层框架MyBaits为什么选择我代码参考数据库参考测试用例参考源码获取前言......
  • 基于springboot+vue.js的短文写作竞赛管理系统附带文章源码部署视频讲解等
    文章目录前言详细视频演示具体实现截图核心技术介绍后端框架SpringBoot前端框架Vue持久层框架MyBaits为什么选择我代码参考数据库参考测试用例参考源码获取前言......
  • Java 入门指南:Java Socket 网络通信编程
    SocketSocket(套接字)是用于网络通信的编程接口、网络通信的基础,通过它可以实现不同计算机之间的数据传输,应用程序可以通过它发送或接收数据;就像操作文件那样可以打开、读写和关闭。它提供了一种机制,使得计算机之间可以进行数据的发送和接收。套接字允许应用程序将I/O应用......
  • 基于Springboot的档案管理系统
    文章目录项目介绍主要功能截图:部分代码展示设计总结项目获取方式......