线程管理 POSIX线程 线程函数 pthread 主线程与子线程传参 线程的结束 线程的取消操作 线程分离 线程同步 互斥量 条件变量 死锁问题 死锁的检测

本文深入探讨了线程的概念,包括线程与进程的区别、POSIX线程标准及其API,如线程创建、线程同步(互斥量、条件变量)和避免死锁的方法。同时,讲解了线程的生命周期、资源管理和通信,以及线程属性、线程取消和分离。
摘要由CSDN通过智能技术生成

线程管理

线程介绍:

线程就是进程中负责执行的部分,是进程内部的控制序列。它是轻量级的,没有自己独立的内存资源、代码段(text)、数据段(静态数据bss、全局数据段data)、堆(heap)、环境变量、命令行参数、文件描述符、信号处理函数、当前工作目录
但是线程拥有独立的栈内存,也就是说它有自己独立的局部变量
 一个进程中至少有一个线程,我们把它叫做主线程,也可以再创建多个线程

注意区别:进程是个资源单位,而线程是个执行单位,线程是进程的一部分,进程中正是有了线程才能动起来

POSIX线程:

    1、早期各计算机厂商自己提供私有的线程库,接口实现的差异非常大,不利于开发和移植
    2、1995年,世界标准化组织,制定了统一的线程接口标准,遵循该标准的线程被统称为POSIX线程,简称pthread
    3、pthread包含一个头文件pthread.h和一个共享库libpthread.so(-pthread)

线程函数:

    #include <pthread.h>

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
    功能:创建一个线程
    thread:输出型参数,用于返回新创建线程的线程ID
    attr:线程属性,一般写NULL即可
    start_routine:线程的入口函数,相当于主线程的main函数
    arg:传递给线程入口函数的参数
    返回值:成功返回0,失败返回-1

    注意:c从表面上来看当主线程结束,子线程会跟着一起结束,但事实情况并不是这样,子线程之所以结束是因为主线程执行了main函数中隐藏的return语句,导致整个进程退出,所以子线程才结束,如果主线程调用了pthread_exit自杀,这样就没有执行隐藏的return语句,进程就不会结束,子线程也不会结束

    int pthread_join(pthread_t thread, void **retval);
    功能:等待指定的线程结束,回收其资源,获取返回值
    thread:等待的线程ID
    retval:用于存储线程的返回值

    pthread_t pthread_self(void);
    功能:获取当前线程的ID

    int pthread_equal(pthread_t t1, pthread_t t2);
    功能:用于判断两个线程ID是否相等
    返回值:相同返回非0数,不同返回0

    void pthread_exit(void *retval);
    功能:结束当前线程
    retval:返回给pthread_join函数,作为线程结束的返回值

    int pthread_cancel(pthread_t thread);
    功能:让指定的线程结束

    int pthread_setcancelstate(int state, int *oldstate);
    功能:设置当前线程是否能被取消
    state:
        PTHREAD_CANCEL_ENABLE       允许取消
        PTHREAD_CANCEL_DISABLE      禁止取消
    oldstate:
        获取线程旧的取消状态

    int pthread_detach(pthread_t thread);
    功能:与指定的子线程分离,让它自己回收资源
    thread:子线程的进程ID

主线程与子线程传参:

1、创建线程时传参
   把传给子线程的数据的内存首地址写在pthread_create函数的最后一个参数
   是否要进行传参与数据在哪块内存无关,与数据的作用域有关
2、线程的返回值
   返回一个地址,该地址指向一块内存,里面存储着要返回给主线程的数据。
   但该内存不可以是线程的栈内存,因为线程一旦结束它的栈内存会被释放

线程的结束:

    1、从线程入口函数return
    2、调用pthread_exit函数
    注意:如果线程调用exit函数,将结束整个进程

线程的取消操作:

一个线程让另一个线程结束,但也要看接收者是否同意取消

线程分离:

主线程创建子线程后,他可以等待子线程结束(回收资源)
 当主线程与子线程分离后,子线程可以自己回收资源

//销毁线程属性结构体            // 初始化线程属性结构体
pthread_attr_destroy            pthread_attr_init

//获取线程内存警戒区大小        //设置线程内存警戒区大小
pthread_attr_getguardsize       pthread_attr_setguardsize

//获取线程的调度策略来源        //设置线程的调度策略来源
pthread_attr_getinheritsched    pthread_attr_setinheritsched
    PTHREAD_INHERIT_SCHED       默认继承创建者的调度策略
    PTHREAD_EXPLICIT_SCHED     根据参数决定(getschedpolicy、getschedparam才有意义)

//获取线程的调度策略            //设置线程的调度策略
pthread_attr_getschedpolicy    pthread_attr_setschedpolicy
    SCHED_FIFO      先进先出策略
    SCHED_RR        轮转策略
    SCHED_OTHER     普通策略(默认,优先级)

//获取线程的优先级
pthread_attr_getschedparam    pthread_attr_setschedparam

//获取线程的竞争范围
pthread_attr_getscope    pthread_attr_setscope
    PTHREAD_SCOPE_SYSTEM        在系统内存竞争
    PTHREAD_SCOPE_PROCESS       进程内竞争,但Linux不支持该选项

//获取栈内存的起始地址和大小
pthread_attr_getstack    pthread_attr_setstack

//获取栈内存的起始地址
pthread_attr_getstackkaddr     pthread_attr_setstackkaddr

//获取栈内存的大小
pthread_attr_getstacksize     pthread_attr_setstacksize    

线程同步:

当多个线程同时访问同一个资源时,如果不进行协调可能会产生数据混乱,操作失效等现象。
我们需要使用一些特殊的技术保障线程之间协同工作,这些技术叫线程同步技术

互斥量:

pthread_mutex_t 也叫互斥锁

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);
功能:初始化互斥量

int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:给互斥量加锁,如果该互斥量已经被加锁,该函数会被阻塞

int pthread_mutex_trylock(pthread_mutex_t *mutex);
功能:尝试给互斥量加锁,如果不能则立即返回

int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:给互斥量解锁

int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:销毁互斥量

条件变量:

pthread_cond_t  能够让进程进入睡眠的对象,当一个线程达到特定的条件后可以睡入条件变量,然后在某个时刻被其它线程叫醒
    //必须与互斥量配合使用

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
功能:初始化条件变量

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
功能:让当前线程睡入cond条件变量,并自动解锁

int pthread_cond_signal(pthread_cond_t *cond);
功能:叫醒条件变量中的一个线程,线程会从pthread_cond_wait返回,并对互斥常量加锁,如果无法成功加锁则继续阻塞

int pthread_cond_broadcast(pthread_cond_t *cond);
功能:叫醒条件变量中的所有线程,条件变量中的线程会从pthread_cond_wait返回,并对互斥常量加锁,如果无法成功加锁则继续阻塞

int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t  *mutex,  const   struct timespec *abstime);
功能:睡入条件变量,并自动解锁,并设置睡眠时间

int pthread_cond_destroy(pthread_cond_t *cond);
功能:销毁条件变量

死锁问题:

1、死锁的定义
	多个进程或线程互相等待对方的资源,在得到对象的资源之前,都不会释放自己的资源,这种造成循环等待的现象叫死锁

2、产生死锁的四大必要条件
        a、资源互斥不能共享
        b、占用且等待
        c、资源不可剥夺
        d、环路等待
3、防止产生死锁方法
	1、破坏互斥条件
		想办法让资源能够共享,解决方法就是增加资源
		缺点:如果资源是硬件,可能有经济上的浪费
	2、破坏请求并保持条件
		在程序运行前一次分配所有它所需要的资源,否则不执行
        缺点:可能会浪费系统资源,因为有些资源可能短时间用不上
    3、破坏不可剥夺的条件
        当请求新的资源失败时释放旧的资源,过一段时间后再重新获取所有资源
        缺点:返回的释放申请资源会浪费时间
    4、破坏循环等待的条件
        把所有的资源进行编号,所有线程按照顺序进行请求资源
        缺点:编号必需要稳定,这样就限制了新的资源加入

4、死锁的检测

1、画出资源的分配简图2
 2、简化资源分配图
 3、按照产生死锁的四大条件来检查是否有请求环路
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值