相关疑难解决方法(0)

递归锁定(互斥锁)与非递归锁定(互斥锁)

POSIX允许互斥锁递归.这意味着同一个线程可以锁定相同的互斥锁两次并且不会死锁.当然它还需要解锁两次,否则没有其他线程可以获得互斥锁.并非所有支持pthread的系统都支持递归互斥锁,但如果它们想要符合POSIX,则必须使用.

其他API(更高级别的API)通常也提供互斥锁,通常称为锁定.一些系统/语言(例如Cocoa Objective-C)提供递归和非递归互斥体.有些语言也只提供一种或另一种语言.例如,在Java中,互斥锁总是递归的(同一个线程可能在同一个对象上"同步"两次).根据它们提供的其他线程功能,没有递归互斥体可能没有问题,因为它们可以很容易地自己编写(我已经在更简单的互斥/条件操作的基础上自己实现了递归互斥锁).

我真的不明白:什么是非递归互斥量有用?如果它锁定相同的互斥锁两次,为什么我想要一个线程死锁?即使是可以避免这种情况的高级语言(例如测试它是否会死锁并抛出异常)通常也不会这样做.他们会让线程陷入僵局.

这只适用于我意外锁定它两次并且只解锁一次的情况,并且在递归互斥锁的情况下,它会更难找到问题,所以相反我立即死锁以查看错误锁定出现在哪里?但是我不能在解锁时返回一个锁定计数器并且在某种情况下,我确定我释放了最后一个锁并且计数器不为零,我可以抛出异常或记录问题吗?或者是否有其他更有用的非递归互斥体用例我看不到?或者它可能只是性能,因为非递归互斥体可能比递归互斥体略快?但是,我对此进行了测试,差异确实不大.

multithreading mutex deadlock locking recursive-mutex

176
推荐指数
6
解决办法
11万
查看次数

从DllMain()锁定时,Visual Studio 2012中的C++ 11 std :: mutex死锁

我看到一个死锁,std::mutex当互斥锁被锁定时,DllMain()下面是一个最小的DLL测试用例,它为我展示了问题.我的实际代码执行互斥锁定,因为它使用的成员函数在正常函数期间也可以在初始化之外使用.

我认为问题是调度程序在main()线程的调用堆栈和调度程序生成的另一个线程(可能)之间的死锁.死锁似乎在main()实际执行之前发生.

我将不胜感激任何关于如何修复/解决死锁的建议.

简单的DLL:

static void testFunc()
{
    std::mutex mtx;
    mtx.lock();

    mtx.unlock();
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        testFunc ();
        break;

    case DLL_THREAD_ATTACH:
        testFunc ();
        break;

    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
Run Code Online (Sandbox Code Playgroud)

在死锁时,进程中有两个线程:

Not Flagged >   6408    0   Main Thread Main Thread msvcr110d.dll!Concurrency::details::SchedulerBase::SchedulerBase    Normal
Not Flagged     7600    0   Worker Thread   ntdll.dll!_TppWaiterpThread@4() ntdll.dll!_NtDelayExecution@8   Normal
Run Code Online (Sandbox Code Playgroud)

这是main()线程的调用堆栈:

    ntdll.dll!_NtWaitForKeyedEvent@16() Unknown …
Run Code Online (Sandbox Code Playgroud)

c++ dll multithreading visual-studio visual-studio-2012

4
推荐指数
1
解决办法
3762
查看次数