概述
线程安全及可重入概念
线程安全:多个线程并发同一段代码时,不会出现不同的结果,常见于对全局变量和静态变量进行操作,并且没有被锁保护的情况下,会出现线程不安全的问题。
可重入:同一个函数被不同的执行流调用,当前一个流程没有被执行完,就有其他的执行流再次进入称为重入,一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数称为可重入函数,(因此可以看出,一个函数可重入,一定是线程安全的),否则称为不可重入函数。
- 常见线程不安全的的情况
(1)不保护共享变量的函数
(2)函数状态锁着被调用,状态发生变化的函数
(3)返回指向静态变量指针的函数
(4)调用线程不安全函数的函数 - 常见线程安全的情况
(1)每个线程对全局变量或者静态变量只有读取的权限,没有写入的权限,这些线程一般是安全的
(2)类或者接口对于线程来说都是原子操作
(3)多个线程之间的切换不会导致该接口的指向结果存在二义性 - 常见不可重入的情况
(1)调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的
(2)调用了标准I/O库函数,因为标准I/O库很多实现是以不可重入的方式是用全局数据结构
(3)可重入函数体内使用了静态的数据结构 - 常见可重入情况
(1)不使用全局变量或者静态变量
(2)不使用用malloc或者new开辟的空间
(3)不调用不可重入函数
(4)不返回静态或全局数据,所有数据都由函数的调用者提供
(5)是用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据 - 可重入与线程安全的联系
函数可重入,就是线程安全的;函数不可重入,就是不能被多个线程使用,可能引发线程安全问题;若一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的 - 可重入与线程安全区别
可重入函数是线程安全的一种,线程安全不一定是可重入的,而可重入函数一定是线程安全的;若对临界资源的访问加上锁,则这个函数是线程安全的,但是如果这个重入函数若锁还未被释放则会产生死锁,因此是不可重入的
死锁
- 死锁概念
多个执行流对锁资源进行争抢访问,因为推进顺序不当,而导致互相等待,最终造成程序流程无法继续的情况。例如A申请B中不会释放的资源,B申请C中不会释放的资源,C申请A中不会释放的资源,这样就会处于永久等待状态。 - 死锁四个必要条件(重要,必须满足)
(1)互斥条件:一个资源每次只能被一个执行流使用
(2)请求和保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放
(3)不剥夺条件:一个执行流已获得的资源,在未使用完之前,不能强行剥夺
(4)循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系
例如线程1申请A锁,申请完申请B锁,线程2申请B锁,申请完申请A锁,因此线程1申请完A锁想要申请B锁,申请不到,线程1挂起,自己申请的锁保持不放,没有释放A锁,因此线程2想要申请A锁申请不到,线程2挂起,自己申请的锁保持不放,没有释放B锁,意味着线程1 2永远不会被唤醒,产生死锁。
只有一把锁,一个线程也可能产生死锁,例如线程申请了锁,然后又申请了一次,没有申请成功,挂起,想要唤醒就要释放这个锁,但是此时线程挂起,这个锁被这个线程拿着,没有释放这个锁,因此就产生了死锁。 - 避免死锁
(1)破坏死锁的四个必要条件(互斥条件不能破坏)
(2)加锁顺序一致
(3)避免锁未被释放的场景
(4)资源一次性分配 - 避免死锁算法
(1)死锁检测算法
(2)银行家算法
最后
以上就是无聊电脑为你收集整理的Linux:线程安全、可重入、死锁的全部内容,希望文章能够帮你解决Linux:线程安全、可重入、死锁所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复