本文主要是介绍C++ 的死锁问题的发生和避免,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
C/C++程序中产生死锁的原因很多,本文大致归纳了下面几类,分别做分析。
1.单线程/进程多次加锁导致死锁
单线程导致死锁的情况一般是由于调用了引起阻塞的函数,比如(copy_from_user()、copy_to_ser()、和kmalloc()),阻塞后进行系统调度,调度的过程中有可能又调用了之前获取锁的函数,这样必然导致死锁。
还有一种就是自旋锁函数在没有释放锁马上又进行申请同一个自旋锁,这样的低级问题也是会导致自旋锁。
简单的说,就是在单个线程中,创建了一个不可重复加锁的锁,然后,调用了加锁函数,在没有调用解锁函数的情况下,再次调用加锁函数导致的死锁。
例如,std::recursive_mutex 是可重复加锁的Recursive锁,std::mutex是不可重复加锁的NonRecursive锁。下面的例子中,在main函数中,分别创建了一个Recursive锁,一个NonRecursive锁:
#include <chrono>
#include <iostream>
#include <mutex>int main(int argc, char *argv[])
{std::mutex mutex;std::recursive_mutex mutex_recursive;while(true){//Recursive锁,尝试多次加锁mutex_recursive.lock();std::cout << "11111" << std::endl;mutex_recursive.lock();std::cout << "22222" << std::endl;mutex_recursive.unlock();std::cout << "33333" << std::endl;mutex_recursive.unlock();//NonRecursive锁,尝试多次加锁mutex.lock();std::cout << "AAAAAAA" << std::endl;mutex.lock();std::cout << "BBBBBBB" << std::endl;mutex.unlock();std::cout << "CCCCCC" << std::endl;mutex.unlock();std::this_thread::sleep_for(std::chrono::milliseconds(5000));}return 0;
}
以上程序输出:
11111
22222
33333
AAAAAAA
从输出看,输出“AAAAAAA”后,第二次对NonRecursive类型的锁加锁,程序就卡住不往下执行了。可见,对于Recursive类型的锁,同一个线程多次加锁都不会死锁;但是,对于NonRecursive类型的锁,同一个线程多次加锁,就会导致死锁。
综上所述,对于单线程/进程程序,只要创建Recursive类型的锁,就可以保证不发生死锁问题。
2.多线程/进程的死锁
大多数情况下,程序发生的死锁都是发生在多线程/进程情况下,因为,相对于单线程/进程程序,多线程/进程程序在代码执行时序上会更复杂,程序员更不好把握。
出现以下四种情况会产生死锁:
2.1 忘记解锁
两个线程/ 进程共享同一个资源,考虑如下时序:
1.其
这篇关于C++ 的死锁问题的发生和避免的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!