[英]Unexpected behavior using std::try_to_lock
当我尝试运行以下代码时,我得到了令人惊讶和冲突的行为。
#include <iostream>
#include <mutex>
int main() {
std::mutex mtx;
std::unique_lock<std::mutex> lock1(mtx);
std::unique_lock<std::mutex> lock2(mtx, std::try_to_lock);
std::cout << "lock1 owns lock: " << lock1.owns_lock() << std::endl;
std::cout << "lock2 owns lock: " << lock2.owns_lock() << std::endl;
}
当我在我的计算机上运行它时(带有 clang++ 4.0.1 或 g++ 7.3.0 的 linux),它打印出lock1
和lock2
拥有锁(令人惊讶)。 当我在cpp.sh
上运行它时,它说lock1
拥有,但lock2
不拥有锁(我所期望的)。
所有都使用 C++11 和-Wall
没有优化。
如std::unique_lock
构造函数的文档中所述:
- 尝试通过调用 m.try_lock() 在不阻塞的情况下锁定关联的互斥锁。 如果当前线程已经拥有互斥锁,则行为未定义,除非互斥锁是递归的。
重点是我的。 由于std::mutex
不是递归的,因此您具有未定义的行为 - std::mutex::try_lock()
如果 try_lock 由已经拥有互斥锁的线程调用,则行为未定义。
正如在此处回答的那样,根据 C++ 标准,锁定当前线程已拥有的互斥锁是未定义的行为,但您似乎知道您的实现基于 POSIX 线程,它具有一组不同的要求:
pthread_mutex_trylock()
函数应等效于pthread_mutex_lock()
,但如果 mutex 引用的互斥对象当前被锁定(由任何线程,包括当前线程),则调用应立即返回。
您所观察到的很可能是由于您没有使用-pthread
标志构建代码造成的。 GNU C++ 库检测程序是否与libpthread.so
链接,如果没有,则所有对lock
/ unlock
函数的调用都将变为无操作。
你可以在这里找到一些信息:
__gthread_mutex_lock
是一个单行函数,它转发到pthread_mutex_lock
。 如果您不链接到libpthread.so
则使用 GNU libc,那么pthread_mutex_lock
是一个无操作的函数,什么也不做。 调用它比花时间检查线程是否处于活动状态要快。
或者您可以自己检查头文件中std::mutex::lock
的源代码。 你会看到这样的事情:
void
lock()
{
int __e = __gthread_mutex_lock(&_M_mutex);
// EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
if (__e)
__throw_system_error(__e);
}
static inline int
__gthread_mutex_lock (__gthread_mutex_t *__mutex)
{
if (__gthread_active_p ())
return __gthrw_(pthread_mutex_lock) (__mutex);
else
return 0;
}
如果当前进程中不存在libpthread.so
函数__gthread_active_p
将返回0
,从而使互斥锁成为无操作。
添加-pthread
将解决您的问题,但您不应该依赖于此 - 正如您的案例所证明的那样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.