简体   繁体   English

使用 std::try_to_lock 的意外行为

[英]Unexpected behavior using std::try_to_lock

I get surprising and conflicting behavior when I try to run the following code.当我尝试运行以下代码时,我得到了令人惊讶和冲突的行为。

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

When I run this on my computer (linux with either clang++ 4.0.1 or g++ 7.3.0) it prints out that both lock1 and lock2 own the lock (surprising).当我在我的计算机上运行它时(带有 clang++ 4.0.1 或 g++ 7.3.0 的 linux),它打印出lock1lock2拥有锁(令人惊讶)。 When I run this on cpp.sh it says that lock1 does own, but lock2 does not own the lock (what I expected).当我在cpp.sh上运行它时,它说lock1拥有,但lock2不拥有锁(我所期望的)。

All are using C++11 and -Wall without optimizations.所有都使用 C++11 和-Wall没有优化。

As stated in documentation for std::unique_lock constructor:std::unique_lock构造函数的文档中所述:

  1. Tries to lock the associated mutex without blocking by calling m.try_lock().尝试通过调用 m.try_lock() 在不阻塞的情况下锁定关联的互斥锁。 The behavior is undefined if the current thread already owns the mutex except when the mutex is recursive.如果当前线程已经拥有互斥锁,则行为未定义,除非互斥锁是递归的。

Emphasis is mine.重点是我的。 Since std::mutex is not recursive you have undefined behaviour - std::mutex::try_lock()由于std::mutex不是递归的,因此您具有未定义的行为 - std::mutex::try_lock()

If try_lock is called by a thread that already owns the mutex, the behavior is undefined.如果 try_lock 由已经拥有互斥锁的线程调用,则行为未定义。

As was answered here, locking mutex that is already owned by the current thread is an undefined behavior according to the C++ standard, but it seems that you know that your implementation is based on POSIX Threads, which has a different set of requirements:正如在此处回答的那样,根据 C++ 标准,锁定当前线程已拥有的互斥锁是未定义的行为,但您似乎知道您的实现基于 POSIX 线程,它具有一组不同的要求:

The pthread_mutex_trylock() function shall be equivalent to pthread_mutex_lock() , except that if the mutex object referenced by mutex is currently locked ( by any thread, including the current thread ), the call shall return immediately. pthread_mutex_trylock()函数应等效于pthread_mutex_lock() ,但如果 mutex 引用的互斥对象当前被锁定(由任何线程,包括当前线程),则调用应立即返回。

What you are observing is most likely caused by you not building your code using -pthread flag.您所观察到的很可能是由于您没有使用-pthread标志构建代码造成的。 GNU C++ library detects if program is linked against libpthread.so and if it is not, then all calls to lock / unlock functions are turned into no-op. GNU C++ 库检测程序是否与libpthread.so链接,如果没有,则所有对lock / unlock函数的调用都将变为无操作。

You can find some information here :你可以在这里找到一些信息:

__gthread_mutex_lock is a one-line function that forwards to pthread_mutex_lock . __gthread_mutex_lock是一个单行函数,它转发到pthread_mutex_lock Using GNU libc if you don't link to libpthread.so then pthread_mutex_lock is a no-op function that does nothing .如果您不链接到libpthread.so则使用 GNU libc,那么pthread_mutex_lock是一个无操作的函数,什么也不做 It is quicker to just call it than to spend time checking if threads are active.调用它比花时间检查线程是否处于活动状态要快。

Or you can check the source code for std::mutex::lock in your header files yourself.或者您可以自己检查头文件中std::mutex::lock的源代码。 You will see something like this:你会看到这样的事情:

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

Function __gthread_active_p will return 0 if libpthread.so is not present in the current process, making mutex locking a no-op.如果当前进程中不存在libpthread.so函数__gthread_active_p将返回0 ,从而使互斥锁成为无操作。

Adding -pthread will fix your problem, but you shouldn't rely on this - as demonstrated by your case.添加-pthread将解决您的问题,但您不应该依赖于此 - 正如您的案例所证明的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM