2013-07-18 60 views
5

简单的问题 - 基本上,我必须解锁一个互斥锁,还是我可以简单地使用范围操作符,互斥锁将自动解锁?互斥锁在超出范围时是否解锁?

即:

{ 
    pthread_mutex_lock (&myMutex); 
    sharedResource++; 
} // my mutex is now unlocked? 

或者我应该:

{ 
    pthread_mutex_lock (&myMutex); 
    sharedResource++; 
    pthread_mutex_unlock (&myMutex); 
} 
+5

您使用哪种互斥体实现?除非你是互斥体实现支持RAII,否则你可能不得不明确地解锁互斥体。 – Void

+0

Thanks @Void。我正在使用pthread.h。即pthread_mutex_unlock()和pthread_mutex_lock()。什么是RAII? –

+3

@AmitNayar:请参阅http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization。这可能是C++中最重要的成语,因为如果没有它,管理内存和其他动态资源几乎是不可能的。 –

回答

16

在您的示例中互斥量未超出范围;并且编译器无法知道某个函数是否需要在范围的末尾调用,所以第一个示例确实是而不是解锁了互斥锁。

如果您正在使用(容易出错)函数来锁定和解锁互斥锁,则需要确保始终调用unlock() - 即使受保护的操作抛出异常。

要做到这一点,最好的办法是使用RAII类来管理锁,因为你会为需要使用后释放任何其他资源:

class lock_guard { 
public: 
    explicit lock_guard(mutex & m) : m(m) {mutex_lock(m);} 
    ~lock_guard() {mutex_unlock(m);} 

    lock_guard(lock_guard const &) = delete; 
    void operator=(lock_guard &) = delete; 

private: 
    mutex & m; 
}; 

// Usage 
{ 
    lock_guard lock(myMutex); 
    shared_resource++; 
} // mutex is unlocked here (even if an exception was thrown) 

在现代C++中,使用std::lock_guardstd::unique_lock为这个。

2

使用RAII范围方法要好得多,因为它保证了互斥总是会即使在异常或早期的脸解锁返回。

如果您有权访问C++ 11,但您可能会考虑使用std::atomic<int>而不是在这种情况下,您不需要将其锁定为增量。

2

在这种情况下,当该代码超出范围时,不会解锁互斥锁

RAII之后的互斥锁使用这样一个事实,即当非堆分配对象超出范围时,会自动调用析构函数。一旦锁定互斥锁的对象超出了范围,它就会解锁互斥锁。在你的代码中,在大括号的范围内没有任何对象被分配,所以一旦范围结束,互斥锁就没有可能被解锁。

例如,使用从Qt库QMutexLocker,可以确保当范围结束你的互斥量被释放:

{ 
    QMutexLocker locker(myMutex); 
    if(checkSomething()) 
    { 
     return; 
    } 
    doSomething(); 
} 

此代码是类似于:

{ 
    mutex_lock(myMutex); 
    if(checkSomething()) 
    { 
     mutex_unlock(myMutex); 
     return; 
    } 
    doSomething(); 
    mutex_unlock(myMutex); 
} 

虽然布赖恩尼尔指出,它不能安全地处理checkSomething()doSomething()引发异常的情况。

Qt的QMutexLocker的替代方案是STD的std::lock_guard

+2

如果您考虑异常,则这两个代码片段不等效。为了使它们等价,你必须在'checkSomething'和'doSomething'周围添加try/catch块。只是另一个更喜欢你的第一个使用RAII的例子的原因。 :) –

+0

好点,@BrianNeal。我已经更新了答案。我明确指出,不要使用异常,因为它们对于'Qt'基础结构并不是必须的,所以我很容易忘记其他人需要对它们进行解释。 –