pthread互斥锁失效求助:未解锁时其他线程可进入临界区
互斥锁失效:线程重复锁定同一pthread_mutex_t的问题分析
问题现象
运行日志显示同一互斥锁被两个线程同时持有,违背互斥锁的基本语义:
checkEvents lock eventloop mutex. <-- 互斥锁已被锁定
Eventloop::remove lock eventloop mutex. <-- 另一线程再次锁定同一互斥锁
checkEvents unlock eventloop mutex.
核心原因分析
问题的根源在于Timer类中多处锁操作错误,触发了未定义行为,间接破坏了Eventloop互斥锁的正常工作:
1. 锁操作拼写错误(致命问题)
Timer的析构函数、start方法、handle方法中,均将pthread_mutex_unlock误写为pthread_mutex_lock,导致同一线程对非递归互斥锁重复加锁。pthread默认互斥锁为非递归类型,重复加锁会触发未定义行为——操作系统可能认为锁状态损坏,进而允许其他线程绕过互斥逻辑。
2. 内存删除逻辑错误
Eventloop::remove方法中,错误地删除eventList.back()而非当前匹配的事件元素,导致内存管理混乱,进一步加剧未定义行为的发生。
3. Timer成员互斥锁未初始化
Timer类的成员互斥锁mutex未在构造函数中初始化,直接使用会导致锁状态异常。
具体代码问题点
Timer.cpp中的错误锁操作
- 析构函数:最后一行应为
unlock而非lockTimer::~Timer() { std::cout << "Timer destructor start\n"; pthread_mutex_lock(&mutex); Eventloop::remove(&timerEvent); pthread_mutex_lock(&mutex); // ❌ 应为pthread_mutex_unlock std::cout << "Timer destructor end \n"; } - start方法:修改参数后应为
unlock而非lockvoid Timer::start(uint16_t ms) { pthread_mutex_lock(&mutex); durMs = ms; startTime = getTimeMs(); pthread_mutex_lock(&mutex); // ❌ 应为pthread_mutex_unlock stopFlag = false; } - handle方法:逻辑处理后应为
unlock而非lockvoid Timer::handle() { pthread_mutex_lock(&mutex); if (!stopFlag) { if (getTimeMs() - startTime >= durMs) { timerTask->runTimerTask(); startTime = getTimeMs(); } } pthread_mutex_lock(&mutex); // ❌ 应为pthread_mutex_unlock }
Eventloop.cpp中的删除逻辑错误
void Eventloop::remove(Event **event) { pthread_mutex_lock(&mutex); std::cout << "Eventloop::remove lock eventloop mutex. \n"; std::list<Event *>::iterator it; for(it = eventList.begin() ; it != eventList.end() ; it++) { std::cout << "event = " << (*it) << "\n"; if((*it) == *event) { delete eventList.back(); // ❌ 应删除当前匹配的(*it) eventList.remove(*event); } } pthread_mutex_unlock(&mutex); std::cout << "Eventloop::remove unlock eventloop mutex. \n"; }
修复方案
1. 修正Timer类的锁操作
将所有错误的pthread_mutex_lock替换为pthread_mutex_unlock,并初始化/销毁Timer的成员互斥锁:
// Timer构造函数:初始化成员互斥锁 Timer::Timer(TimerTask *_timerTask) { pthread_mutex_init(&mutex, NULL); timerEvent = new TimerEvent(this); Eventloop::append(&timerEvent); std::cout << "Event in Timer Constructor= " << timerEvent << "\n"; timerTask = _timerTask; stopFlag = false; } // Timer析构函数:修正锁操作并销毁互斥锁 Timer::~Timer() { std::cout << "Timer destructor start\n"; pthread_mutex_lock(&mutex); Eventloop::remove(&timerEvent); pthread_mutex_unlock(&mutex); pthread_mutex_destroy(&mutex); std::cout << "Timer destructor end \n"; } // Timer::start:修正锁操作 void Timer::start(uint16_t ms) { pthread_mutex_lock(&mutex); durMs = ms; startTime = getTimeMs(); pthread_mutex_unlock(&mutex); stopFlag = false; } // Timer::handle:修正锁操作 void Timer::handle() { pthread_mutex_lock(&mutex); if (!stopFlag) { if (getTimeMs() - startTime >= durMs) { timerTask->runTimerTask(); startTime = getTimeMs(); } } pthread_mutex_unlock(&mutex); }
2. 修正Eventloop::remove的删除逻辑
改为删除当前匹配的元素,并避免迭代器失效:
void Eventloop::remove(Event **event) { pthread_mutex_lock(&mutex); std::cout << "Eventloop::remove lock eventloop mutex. \n"; std::list<Event *>::iterator it; for(it = eventList.begin() ; it != eventList.end() ; ) { std::cout << "event = " << (*it) << "\n"; if((*it) == *event) { delete (*it); it = eventList.erase(it); } else { ++it; } } pthread_mutex_unlock(&mutex); std::cout << "Eventloop::remove unlock eventloop mutex. \n"; }
验证建议
- 运行修复后的代码,观察日志是否再出现同一互斥锁被多线程同时持有的情况。
- 添加线程ID打印(如
pthread_self()),确认加锁/解锁操作的线程一致性。 - 显式指定互斥锁类型为普通锁,避免依赖默认行为:
pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); pthread_mutex_init(&Eventloop::mutex, &attr); pthread_mutexattr_destroy(&attr);
内容的提问来源于stack exchange,提问作者Pouya Imani
相关产品推荐
相关产品推荐

