【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都陷入了一直的等待中。

死锁四个必要条件

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

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

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

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

避免死锁

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

相关推荐
皮皮哎哟2 天前
Linux多线程通信:告别数据混乱
linux·互斥锁·进程间通信·信号量
熬夜有啥好2 天前
Linux软件编程——线程间的通信
互斥锁·信号量·软件编程·多线程间的通信
嵌入小生0073 天前
线程间通信---嵌入式(Linux)
linux·c语言·vscode·嵌入式·互斥锁·线程间通信·信号量
西门吹雪分身4 天前
JUC之可重入锁
java·juc·死锁·公平锁·非公平锁
闲人编程11 天前
Redis分布式锁实现
redis·分布式·wpf·进程··死锁·readlock
谷公子的藏经阁19 天前
AXI各通道握手依赖
valid·axi·死锁·握手·ready
谷公子的藏经阁19 天前
讲个AXI死锁场景
cpu·axi·死锁·deadlock·axi2ahb
ん贤21 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
Trouvaille ~1 个月前
【Linux】线程同步与互斥(一):线程互斥原理与mutex详解
linux·运维·服务器·c++·算法·线程·互斥锁
egoist20231 个月前
[linux仓库]线程池(单例模式)、线程安全与重入、死锁[线程·拾]
linux·单例模式·饿汉模式·懒汉模式·线程安全·死锁·重入问题