STD :: Mutex如何在不同的线程中解锁

How std::mutex got unlocked in different thread?

本文关键字:线程 解锁 Mutex STD      更新时间:2023-10-16

i正在阅读二进制信号量和静音之间的差异(二进制信号量和mutex之间的差异(,我想验证的一件事是,当任务锁定(获取(互斥s时,只有它才能可以解锁(释放(。如果另一个任务试图解锁互斥X,则尚未锁定(因此没有(,则遇到错误条件,最重要的是,Mutex未解锁,并且我在C 14中的代码下方创建了这一点:

#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;
}

但是,在此示例中,我能够从不拥有它的线程中解锁Mutex,因此只需要有一些理解的差距,或者在C 14 std :: mutex?

std::mutex上调用 try_lock(不是递归的(,呼叫线程,在不呼叫线程拥有的静音上调用 unlock导致不确定的行为。

它似乎成功,可能会失败并抛出异常,它可能会格式化您的硬盘驱动器,可能会召唤鼻恶魔,可能会时间旅行并为您纠正您的代码,或者可能会做其他事情。就标准而言,是允许的。

呼叫 unlock的先决条件是持有静音的所有权,根据(std(30.4.1.2:

表达式M.unlock((应具有良好的形式,并具有以下语义:

要求:呼叫线应拥有静音。

由于执行 increment1的线程不持有静音的所有权,因此引爆了未定义的行为。

来自cppReference std::mutex(强调矿山(:

如果在仍然由任何线程所有的同时销毁二线,或线程在拥有互斥品时终止。

std::mutex::try_lock上的同一站点,正如TC在答案中指出的:

如果try_lock是由已经拥有静音的线程调用的,则行为是未定义的。

以及std::mutex::unlock,正如TC在其答案中指出的那样:

静音必须被当前的执行线锁定,否则,行为是未定义的。

您的功能和线程都会导致不确定的行为:

  1. increment调用lock(),然后 try_lock():未定义的行为
  2. increment1在拥有互不个性之前调用 unlock():不确定的行为

,如果您在线程结束之前不致电unlock(),则从increment中删除try_lock()仍会导致不确定的行为。

您应该更喜欢使用std::lock_guard,或者对于简单的int,也可以使用std::atomic