我正在阅读二进制信号量和互斥量(Difference between binary semaphore and mutex)之间的差异,我要验证的一件事是,当任务锁定(获取)互斥锁时,它只能解锁(释放)它。如果另一个任务试图解锁互斥锁它没有锁定(因此不拥有),那么遇到错误条件,最重要的是,互斥锁没有解锁,为此我在c ++ 14中创建了下面的代码:< / p>
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;
int counter;
int i;
std::mutex g_pages_mutex;
void increment()
{
std::cout<<"increment...."<<std::endl;
g_pages_mutex.lock();
bool flag = g_pages_mutex.try_lock();
std::cout<<"increment Return value is "<<flag<<std::endl;
counter++;
std::this_thread::sleep_for(5s);
}
void increment1()
{
std::this_thread::sleep_for(5s);
std::cout<<"increment1...."<<std::endl;
g_pages_mutex.unlock();
counter++;
bool flag = g_pages_mutex.try_lock();
std::cout<<"increment1 Return value is "<<flag<<std::endl;
}
int main()
{
counter = 0;
std::thread t(increment);
std::thread t1(increment1);
t.join();
t1.join();
return 0;
}
然而,通过这个例子,我能够从没有拥有它的线程中解锁互斥锁,所以只是想要有一些理解上的差距,或者这个问题在c ++ 14 std :: mutex中?
答案 0 :(得分:4)
在调用线程拥有的try_lock
(不是递归)上调用std::mutex
,在不属于调用线程的互斥锁上调用unlock
,并在保持时结束线程互斥体,都会导致未定义的行为。
它可能看起来成功,它可能会失败并抛出异常,它可能会格式化您的硬盘驱动器,它可能会召唤鼻子恶魔,它可能会为您旅行并更正您的代码,或者它可能会做其他事情。就标准而言,任何都是允许的。
答案 1 :(得分:0)
来自cppreference std::mutex
(强调我的):
如果互斥锁在被任何线程拥有的情况下被销毁,或线程在拥有互斥锁时终止,则程序的行为是未定义的。
来自std::mutex::try_lock
上的同一网站和TC points out in their answer:
如果已经拥有互斥锁的线程调用了try_lock,则行为未定义。
还有std::mutex::unlock
和TC points out in their answer:
互斥锁必须由当前执行线程锁定,否则行为未定义。
您的函数和线程都会导致未定义的行为:
increment
调用lock()
然后调用try_lock()
:未定义的行为increment1
在拥有互斥锁之前调用unlock()
:未定义的行为如果在线程结束前未调用try_lock()
,则从increment
中删除unlock()
仍会导致未定义的行为。
您应该更喜欢使用std::lock_guard
,或者对于简单的int
,您也可以使用std::atomic
答案 2 :(得分:0)
调用unlock
的前提条件是持有互斥锁的所有权,根据(标准)30.4.1.2:
表达式m.unlock()应格式正确,并具有以下语义:
要求:调用线程应拥有互斥锁。
由于执行increment1
的线程不拥有互斥锁的所有权,它引爆了未定义的行为。