簡體   English   中英

使用 std::try_to_lock 的意外行為

[英]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),它打印出lock1lock2擁有鎖(令人驚訝)。 當我在cpp.sh上運行它時,它說lock1擁有,但lock2不擁有鎖(我所期望的)。

所有都使用 C++11 和-Wall沒有優化。

std::unique_lock構造函數的文檔中所述:

  1. 嘗試通過調用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM