🍑个人主页:Jupiter. 🚀 所属专栏:Linux从入门到进阶 欢迎大家点赞收藏评论😊
目录
-
- `🐎可重入VS线程安全`
-
- `🦈概念`
- `🐬常见的线程不安全的情况`
- [`🦀常见的线程安全的情况 `](#
🦀常见的线程安全的情况
) - `🐢常见不可重入的情况`
- [`🐍常见可重入的情况 `](#
🐍常见可重入的情况
) - [`🐚可重入与线程安全联系 `](#
🐚可重入与线程安全联系
) - [`🐂可重入与线程安全区别 `](#
🐂可重入与线程安全区别
)
- `🐏常见锁概念`
-
- [`🐇死锁 `](#
🐇死锁
) - `🦆死锁四个必要条件(面试题)`
- `🐀避免死锁`
- `🐄避免死锁算法`
- [`🐇死锁 `](#
🐎可重入VS线程安全
🦈概念
- 线程安全:多个线程并发同一段代码时,不会出现不同的结果。常见对全局变量或者静态变量进行操作,并且没有锁保护的情况下,会出现该问题。
- 重入:同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们称之为重入。一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数被称为
可重入函数
,否则,是不可重入函数
。其中,引起线程安全的情况有很多种,引入不可重入函数是其中的一种常见情况。
🐬常见的线程不安全的情况
- 不保护共享变量的函数。
- 函数状态随着被调用,状态发生变化的函数。
- 返回指向静态变量指针的函数。
- 调用线程不安全函数的函数。
🦀常见的线程安全的情况
- 每个线程对全局变量或者静态变量只有读取的权限,而没有写入的权限,一般来说这些线程是安全的。
- 类或者接口对于线程来说都是原子操作。
- 多个线程之间的切换不会导致该接口的执行结果存在二义性。
🐢常见不可重入的情况
- 调用了
malloc/free
函数,因为malloc函数是用全局链表来管理堆的。 - 调用了
标准I/O库函数
,标准I/O库的很多实现都以不可重入的方式使用全局数据结构。 - 可重入函数体内使用了静态的数据结构。
🐍常见可重入的情况
- 不使用全局变量或静态变量。
- 不使用
malloc或者new
开辟出的空间。 - 不调用不可重入函数。
- 不返回静态或全局数据,所有数据都有函数的调用者提供。
- 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
🐚可重入与线程安全联系
- 函数是可重入的,那就是线程安全的。
- 函数是不可重入的,那就不能由多个线程使用,有可能引发线程安全问题。
- 如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。
🐂可重入与线程安全区别
- 可重入函数是线程安全函数的一种。
- 线程安全不一定是可重入的,而可重入函数则一定是线程安全的。
- 如果将对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会产生死锁,因此是不可重入的。
🐏常见锁概念
🐇死锁
- 死锁是指:多线程的锁不合理的使用,导致代码不会向后继续推进的情况。
常见的死锁的情况:
- 在解锁的时候,误写成了加锁;
- 访问一个资源的时候,需要同时持有两把锁,但是在申请的锁的时候的顺序不同,导致线程A在申请锁1的同时,线程B在申请锁2,导致线程A申请不到锁2,线程B申请不到锁1,导致线程一直不能同时持有两把锁,导致代码不会继续推进。
🦆死锁四个必要条件(面试题)
- 互斥条件:一个资源每次只能被一个执行流使用。
- 请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放(可以使用
pthread_mutex_trylock(pthread_mutex *mutex);
破坏该条件)。 - 不剥夺条件:一个执行流已获得的资源,在末使用完之前,不能强行剥夺。
- 循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系(
申请锁的顺序相同即可破坏
)。
🐀避免死锁
- 破坏死锁的四个必要条件。
- 加锁顺序一致。
- 避免锁未释放的场景。
- 资源一次性分配。
🐄避免死锁算法
- 死锁检测算法。
- 银行家算法。