linux系统中线程和线程锁相关函数,及死锁的发生原理和应对方法

线程与线程锁基础

1. 线程的概念
- 线程:是操作系统能够进行调度的最小单位。在同一个进程内,线程共享进程的资源(如内存空间、文件描述符等),但它们也有自己的栈、寄存器等资源。线程的轻量级特性使得它比进程更快地创建和销毁,也使得线程之间的通信更加高效。

 2. 线程相关函数

- pthread_create:
  - 功能:创建一个新线程。
  - 原型:`int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);`
  - 参数:
    - `pthread_t *thread`:线程标识符。
    - `const pthread_attr_t *attr`:线程属性,`NULL` 表示默认属性。
    - `void *(*start_routine)(void *)`:线程函数的起始地址,即线程执行的代码。
    - `void *arg`:传递给线程函数的参数。
  - 返回值:成功返回 `0`,失败返回错误码。

- pthread_join:
  - 功能:等待线程结束,并收集线程的返回值。
  - 原型:`int pthread_join(pthread_t thread, void **retval);`
  - 参数:
    - `pthread_t thread`:要等待的线程标识符。
    - `void **retval`:保存线程返回值的指针。
  - 返回值:成功返回 `0`,失败返回错误码。

`pthread_cancel` 和 `pthread_exit` 是用于线程控制的两个函数,分别用于取消线程和退出线程。

1. `pthread_cancel`:
   - 这个函数用于请求取消一个线程。取消请求并不会立即终止目标线程,而是设置一个取消状态,目标线程根据其取消状态和设置决定何时处理取消请求。目标线程可以选择是否响应取消请求,甚至可以忽略它。
   - 语法:`int pthread_cancel(pthread_t thread);`
   - 参数:`thread` 是要取消的线程的标识符。
   - 返回值:成功时返回0;如果失败,返回错误代码。

2. `pthread_exit`:
   - 这个函数用于终止调用它的线程,并且可以传递一个退出状态给其他线程。调用 `pthread_exit` 后,线程的资源会被清理,并且线程的退出状态会被保存在目标线程的连接(joinable)状态中,供其他线程调用 `pthread_join` 来获取。
   - 语法:`void pthread_exit(void *retval);`
   - 参数:`retval` 是线程的返回值,可以传递任意类型的指针。
   - 这个函数不会返回,因为调用它后线程就会终止。

在多线程编程中,合理使用 `pthread_cancel` 和 `pthread_exit` 是实现线程管理和控制的重要手段。

3. 线程锁的概念
- 线程锁(互斥锁,mutex):在线程并发环境下,用于保护共享资源,确保同一时间只有一个线程可以访问共享资源,从而避免数据竞争和不一致性。

4. 线程锁相关函数

- pthread_mutex_init:
  - 功能:初始化互斥锁。
  - 原型:`int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);`
  - 参数:
    - `pthread_mutex_t *mutex`:要初始化的互斥锁。
    - `const pthread_mutexattr_t *attr`:互斥锁属性,`NULL` 表示默认属性。
  - 返回值:成功返回 `0`,失败返回错误码。

- pthread_mutex_lock:
  - 功能:锁定互斥锁。如果互斥锁已经被其他线程锁定,调用线程会阻塞,直到锁可用。
  - 原型:`int pthread_mutex_lock(pthread_mutex_t *mutex);`
  - 参数:`pthread_mutex_t *mutex`:要锁定的互斥锁。
  - 返回值:成功返回 `0`,失败返回错误码。

- pthread_mutex_trylock:
  - 功能:尝试锁定互斥锁。如果锁不可用,立即返回,而不会阻塞。
  - 原型:`int pthread_mutex_trylock(pthread_mutex_t *mutex);`
  - 返回值:成功返回 `0`,如果锁已经被其他线程锁定,返回 `EBUSY`。

- pthread_mutex_unlock:
  - 功能:解锁互斥锁。
  - 原型:`int pthread_mutex_unlock(pthread_mutex_t *mutex);`
  - 参数:`pthread_mutex_t *mutex`:要解锁的互斥锁。
  - 返回值:成功返回 `0`,失败返回错误码。

- pthread_mutex_destroy:
  - 功能:销毁互斥锁。
  - 原型:`int pthread_mutex_destroy(pthread_mutex_t *mutex);`
  - 参数:`pthread_mutex_t *mutex`:要销毁的互斥锁。
  - 返回值:成功返回 `0`,失败返回错误码。

死锁的概念与应对方法

1. 死锁的发生原理
- 死锁:是一种互相等待的情况,多个线程因为等待资源而相互阻塞,导致它们都无法继续执行。死锁通常发生在多线程程序中,当两个或多个线程都需要访问多个资源时,如果这些资源的获取顺序不当,就可能导致死锁。

- 死锁的四个必要条件:
  1. 互斥条件:每个资源在同一时间只能由一个线程占有。
  2. 持有并等待:一个线程已经持有了一个资源,并且正在等待另一个资源,而该资源被其他线程持有。
  3. 不剥夺:资源不能被强行剥夺,必须由占有的线程自行释放。
  4. 循环等待:存在一个线程序列,使得每个线程都在等待下一个线程持有的资源。

2. 应对死锁的方法

- 预防策略:
  - 破坏互斥条件:通过尽可能减少资源的独占性来预防死锁,例如可以使用共享锁而不是独占锁。
  - 破坏持有并等待条件:线程在获取资源时,如果不能获得所有需要的资源,则释放已经获得的资源,并且重新尝试获取资源。
  - 破坏不剥夺条件:允许线程在需要时释放已经获得的资源,让其他线程可以先获取,稍后再尝试重新获取资源。
  - 破坏循环等待条件:为所有资源分配一个全局唯一的顺序号,线程必须按照这个顺序号来获取资源。

- 避免策略:
  - 银行家算法:这是一种动态地避免死锁的方法,在分配资源时,系统会预先判断这样分配资源是否会导致死锁,如果有可能,则不会进行该资源分配。

- 检测与恢复:
  - 检测:系统可以周期性地检查是否存在死锁。一旦检测到死锁,可以通过回收资源(例如,强制终止某些线程)来打破死锁。
  - 恢复:通过回收资源,通常是通过中止死锁线程或回滚部分操作来恢复系统的正常运行。

- 编码技巧:
  - 尽量简化锁的使用:减少对锁的依赖,能用无锁算法解决的问题尽量不使用锁。
  - 锁的顺序:当一个线程需要同时获取多个锁时,应规定获取锁的顺序,所有线程遵循相同的顺序获取锁,这样可以避免死锁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值