1. 死锁现象的本质与典型场景
死锁是并发编程中最令人头疼的问题之一,它发生在两个或多个线程互相持有对方所需资源的情况下。想象一下这样的场景:线程A持有锁1并请求锁2,而线程B持有锁2并请求锁1,两个线程都在等待对方释放资源,程序就会永久卡死在这个状态。
在实际开发中,我遇到过最典型的死锁场景是数据库事务处理。比如一个转账操作需要锁定两个账户记录:事务1先锁账户A再请求账户B,事务2先锁账户B再请求账户A。当这两个事务并发执行时,死锁就产生了。MySQL的InnoDB引擎虽然能检测到这种死锁并自动回滚其中一个事务,但作为开发者我们更应该从设计层面避免这种情况。
关键提示:死锁的四个必要条件必须同时满足——互斥条件、占有且等待、不可抢占、循环等待。破坏其中任意一个就能预防死锁。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 用C++手动构造死锁实验
让我们通过一个简单的C++示例来演示死锁的产生过程。这个实验需要用到
cpp复制#include <iostream>
#include <thread>
#include <mutex>
std::mutex mutex1, mutex2;
void thread1() {
mutex1.lock();
std::cout << "Thread1 acquired mutex1" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 确保死锁发生
mutex2.lock(); // 这里会阻塞
std::cout << "Thread1 acquired mutex2" << std::endl;
mutex2.unlock();
mutex1.unlock();
}
void thread2() {
mutex2.lock();
std::cout << "Thread2 acquired mutex2" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
mutex1.lock(); //
