【Linux系统】线程安全与死锁问题

前言:

上文我们实现了一个简单线程池并且还设计了线程池的单例模式【Linux实战 】Linux 线程池的设计、实现与单例模式应用-CSDN博客

本文我们来看看,关于线程安全与死锁的问题。


线程安全与重入问题

概念

**线程安全:**就是多个线程在访问共享资源时,能够正确的执行,不会相互干扰或破坏彼此的执行结果。一般情况下,多个线程并发访问一段只有局部变量的代码时,不会出现不同的结果。但是对全局变量或静态变量而言,在没有锁保护的前提下,很容易出现问题。

**重入:**同一个函数被不同的执行流调用,当一个执行流还没有执行完这个函数,另一个执行流就开始执行了这个函数,我们称之为重入,既一个函数多个执行流同时调用。当重入后函数的运行结果不会出现问题,我们称做可重入函数。反之,为不可重入函数。

常见线程不安全情况:

不保护共享变量的函数

函数状态随着被调用,状态发生变化的函数

返回指向静态变量指针的函数

调用线程不安全函数的函数

常见不可重入的情况:

调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的

调用了标准IO库函数,标准IO库的函数很多都是以不可重入的方式设计的

在可重入函数中使用了静态的数据结构

总结

函数是可重入的,那就是线程安全的!而线程是安全的,其函数不一定是可重入的。

思考

STL的容器是否线程安全?

**不安全。**因为STL的设计初衷就是堆性能极致的开发,而一旦涉及到加锁保证安全的环节,其性能就会大打折扣,所以STL是默认是不安全的。在多线程的环境下需要我们自己来保证安全。

智能指针是否安全?

安全。

对于unique_ptr,由于只在当前的代码块中生效,所以不涉及到线程安全问题。

对于shared_ptr,多个对象需要共用一个引用计数,所以会存在线程安全的问题。但是标准库在实现时考虑到了这个问题,让share_ptr的引用计数采用原子性的计数方式,解决了这一问题。


死锁问题

死锁:指在一组进程中的各个进程均占用不会释放的资源,但因互相申请被其他进程不会释放的资源而处于一种永久等待的状态。

申请一把锁是原子的,但申请两把锁是就不一定了。

当线程之间互相申请对方持有的锁,但不释放自己的锁时,就会造成死锁问题。

线程A申请线程B时,B一直不释放,A将会一直进行等待。同样的线程B申请线程A,A一直不释放,B也会一直进行等待。于是线程AB都陷入了一直的等待中。

死锁四个必要条件

互斥条件: 一个资源每次只能被一个执行流使用。

请求与保持: 一个执行流因请求而阻塞时,对已获得的资源保持不放。

不剥夺: 一个执行流获得资源,在未使用完之前,不得被强行剥夺。

循环等待: 若没有申请到资源则进行等待,若干执行流之间形成了头尾相连的循环等待的关系。

避免死锁

想要避免死锁很简单。只需要破坏四个必要条件中的一个即可!

相关推荐
Dlrb12118 小时前
Linux系统编程-信号量(线程同步机制)
linux·条件变量·互斥锁·信号量·线程同步
Dlrb12111 天前
Linux系统编程-线程与多线程模块的封装
linux·线程·互斥锁·线程同步·线程互斥
星马梦缘7 天前
死锁与进程资源分配问题的解法
算法·操作系统·深度优先·死锁
mftang15 天前
Zephyr RTOS 中k_mutex(互斥锁)功能介绍
互斥锁·zephyr·zephyr rtos·k_mutex
长谷深风11115 天前
ConcurrentHashMap线程安全机制解析【个人八股】
哈希算法·cas·线程安全·hashmap·多线程并发·分段锁·桶锁
长谷深风11115 天前
JDK8 HashMap底层结构解析
线程安全·红黑树·hashmap·哈希冲突·负载因子·数组链表·哈希扰动
天海华兮16 天前
【优】B+树,Mysql优化 慢查询 执行计划 优化表结构 避免死锁 大量插入数据大数据后果
b树·mysql·死锁·慢查询·优化表结构·大量插入数据
长谷深风11121 天前
多线程并发实战:从原理到应用【个人八股】
java·并发编程·线程安全·java多线程·synchronized·锁升级
Amazinqc1 个月前
Mysql数据库数据软隔离的并发死锁情况
数据库·mysql·死锁
代码中介商1 个月前
Linux多线程编程完全指南(下):线程同步与互斥锁
linux·redis·线程·互斥锁