系统编程-多线程1

多线程1

目录

多线程1

引入

认识线程

1、线程的概念

2、线程的优缺点

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

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

线程相关函数

1、创建线程

2、线程的退出函数

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

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

5、主动取消一个线程

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

7、线程间通信

补充


引入

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

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

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

-- 在一个进程中同一时刻只能运行一个while(1),而引入线程后就可以同时运行多个

认识线程

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

-- id的格式为%lu 

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

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值