Linux——多线程编程

•。
摘要由CSDN通过智能技术生成

思考:

1.多个进程有相同类型全局数组,要同步,如何高效操作?

        可定义一块共享内存实现。

共享内存需要在进程间共享,因此地址必须在所有进程中都是可见的。为了实现这个目标,操作系统会为共享内存分配一段物理地址空间,这个物理地址空间是连续的。因此,共享内存的地址在每个进程中并不需要是连续的,但是它在物理地址上必须是连续的。在访问共享内存时,需要使用物理地址,而不是进程地址。操作系统会将进程地址映射到物理地址上,以便进程可以访问共享内存。


2.如果某个进程有动态链表,只要变化就要同步给多个进程,应该如何操作作?

        数组地址是连续的可以通过共享内存实现同步,而动态链表创建的各个节点地址不连续,则无法靠共享内存实现。

        若用消息队列,创建一个节点就发送给所有进程,但是消息队列只能被一个进程读取,读取了就没了。        要么每个发一遍。所以这样也都不好实现。

        
3.对于一些要同时之执行多个阻塞任务的进程要如何处理?

(同时操作串口、摄像头、套接字、等待其他进程发送的消息队列等。)

如果用多进程,也会存在要处理数据同步的问题。

那么有没有什么机制可以让所有任务执行时共享一套资源。调度时候分开调度。

        因此引出多线程解决这样的问题。

本项目使用场景

对于多个阻塞任务,必须使用:

        多进程/多线程

所有的临界资源的操作都必须互斥:
        共享内存、消息队列、链表、串口、摄像头、数据库等

线程之间同步机制主要用:

        互斥锁、条件变量

线程基础

        线程有时被称为轻量级进程(LightweightProcess,LWP) ,是程序执行流的最小单元。

        线程是进程中的一个实体,是被系统独立调度和分派的基本单位。
        线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源

引入线程前,进程是资源分配的基本单位,进程也是调度的基本单位。

引入线程后,进程是资源分配的基本单位,线程是调度的基本单位。

线程:
        允许程序执行不止一个任务的机制
        并行执行
        受操作系统异步调度,是操作系统调度的最小单元,
        进程内的不同线程执行是同一程序的不同部分
主线程
        线程可由进程创建,操作系统在创建进程时会创建一个主线程,程序main()函数是主线程的入口。

 1.由于进程的地址空间是私有的,因此在进程间上下文切换时,系统开销比较大在同一个进程中创建的线程共享该进程的地址空间。
2.每一个程序都至少有一个线程,若程序只有一个线程那就是程序本身
3.线程也有就绪、阻塞和运行三种基本状态。


4.Linux里同样用task_struct来描述一个线程。线程和进程都参与统一的调度。
5.多线程通过第三方的线程库来实现 New POSIX ThreadLibrary (NPTL)。

理解 多线程与多进程区别

多线程优点

1.经济实惠
分配的资源少、线程切换比进程切换快、维护线程的开销小
2 资源共享
线程共享它们所属进程的存储器和资源
3 提高了响应速度
允许程序在它的一部分被阻塞或正在执行一个冗长的操作时持续运行
4 提高了多处理机体系结构的利用率

 在多CPU机器中,多线程提高了并发性 

线程共享的资源

一个进程中的多个线程共享以下资源:
可执行的指令
静态数据
进程中打开的文件描述符
信号处理函数

当前工作目录
用户ID
用户组ID

线程私有的资源

每个线程私有的资源如下:
线程ID (TID)
PC(程序计数器)和相关寄存器
堆栈:
        局部变量
        返回地址
错误号(errno)
信号掩码和优先级
执行状态和属性

线程创建

NPTL线程库中提供了如下基本操作
        创建线程
        删除线程
        控制线程
线程间同步和互斥机制
        信号量
        互斥锁
        条件变量

多线程函数:

pthread_create

所需头文件
#include <pthread.h>
函数原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (* routine)(void *), void*arg)
函数参数
thread:创建的线程,
第一个参数是 pthread_t 类型的指针, 线程创建成功的话,会将分配的线程 ID 填入该指针指向的地址。 线程的后续操作将使用该值作为线程的唯一标识。可直接创建一个 pthread_t 的变量,然后,将其地址传入该参数。
attr:指定线程的属性,
第二个参数是 pthread_attr_t 类型的指针, 通过该参数可以定制线程的属性, 比如可以指定新建线程栈的大小、 调度策略等。
PTHREAD_CREATE_DETACHED
分离线程 没有被其他的线程所等待,自己运
行结束了,线程也就终止了,马上释放系统
资源
PTHREAD _CREATE_JOINABLE
线程的默认属性是非分离状态,这种情
况下, 原有的线程等待创建的线程结束。
只有当pthread_join()函数返回时,创
建的线程才算终止,才能释放自己占用
的系统资源。
如果创建线程无特殊的要求, 该值也可以是 NULL, 表示采用默认属性。
routine :线程执行的函数
第三个参数是线程需要执行的函数。 创建线程, 是为了让线程执行一定的任 务。 线程创建成功之后, 该线程就会执行 routine 函数, 该函数之于线程, 就如同 main 函数之于主线程
arg: 传递给线程执行的函数的参数
函数返回值
成功: 0
出错:-1,设置 error number

当调用 pthread_create 函数时,如果将第二个参数设为 NULL,则新线程将使用默认的线程属性。默认的线程属性包括以下内容:

线程的调度策略:默认情况下,新线程的调度策略是 SCHED_OTHER,即普通的轮询调度策略。
线程的栈大小:默认情况下,新线程的栈大小为系统默认值,一般为 2MB 左右。
线程是否继承父线程的线程属性:默认情况下,新线程会继承父线程的线程属性,例如调度策略、栈大小、线程优先级等。

将第二个参数设为 NULL 的意思就是使用默认的线程属性来创建新线程,这样可以简化线程创建的参数,同时保证新线程具有常规的线程属性。在需要更加精细的线程属性配置时,可以通过创建线程属性对象并设置属性值来实现。


pthread_join

pthread_create的第二个参数attr指定线程的属性为 PTHREAD _CREATE_JOINABLE 或者NULL默认属性,则执行完一定要pthread_join
线程执行完后如果不 pthread_join 的话,线程的资源会一直 得不到释放而导致内存泄 漏!
所需头文件
#include <pthread.h>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值