try_lock_for未按预期工作

7

我在尝试处理一些 C++ 代码时遇到了问题,而最终发现问题出在这里:

#include <thread>
#include <atomic>
#include <chrono>
#include <mutex>
#include <iostream>

using namespace std;

void test()
{
  timed_mutex m;
  m.lock();
  std::cout << "Can i have the lock? " << m.try_lock() << std::endl;
  std::cout << "in test(), should block for 10 seconds" << std::endl;
  bool got_lock = m.try_lock_for(std::chrono::seconds(10));
  std::cout << "Now i've blocked, got the lock: " << got_lock << std::endl;
  m.unlock();
}

int main()
{
  thread t = thread(&test);
  t.join();

  return EXIT_SUCCESS;
}

问题在于test()函数根本不会阻塞,即使try_lock返回false。我是否忽略了某些东西,或者这是gcc的一个bug,或者我应该去哪里找出问题所在?感谢任何建议和帮助!
我像这样编译了这个小程序:g++ -pthread -std=c++11 threads.cpp -o threads,如果有帮助的话,这是我的gcc版本和操作系统:
g++ --version
g++ (GCC) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

uname -a
Linux *computername* 3.6.11-1-ARCH #1 SMP PREEMPT Tue Dec 18 08:57:15 CET 2012 x86_64 GNU/Linux

@billz 看起来是这样,它总是几乎瞬间完成,也就是说,我没有看到任何阻塞。 - lfxgroove
是的,我真的不知道接下来该怎么做,也许有人能在ArchLinux上进行测试吗?我想我得去那里发帖了。 - lfxgroove
我可以在archlinux上重现这种行为(相同的gcc,主线3.7内核):real 0m0.004s。这可能与特定的gcc版本有关。 - Alexandre C.
@AlexandreC。好的,谢谢你的尝试!我接下来该怎么做?我需要在Arch Linux的错误跟踪器中提交一个错误报告吗? - lfxgroove
@Anton:这可能与 ArchLinux 没有关系,而是与您的代码中的某些未定义行为、gcc bug、pthreads bug 或其他任何问题有关。我建议您在另一台装有 gcc 4.7.2 的机器上尝试,并且如果行为不正确,请向gcc邮件列表询问他们对您的测试用例的看法。 - Alexandre C.
显示剩余4条评论
1个回答

6
你的代码行为未定义。std :: timed_mutex具有非递归所有权语义。在同一线程上第二次获取锁(包括try_lock系列)是被禁止的。 C ++ 11标准30.4.1.3.1 [thread.timedmutex.class] / p3 / b2:(感谢Howard Hinnant) 程序的行为是未定义的,如果: 一个拥有timed_mutex对象的线程在该对象上调用lock(),try_lock(),try_lock_for()或try_lock_until(); 不推荐在异常安全性方面获取/释放互斥对象的锁定。如果您改为使用unique_lock对象,则可以使用owns_lock()成员函数来帮助您。 同时,对于你的目的,递归互斥锁是无用的,因为“递归”仅意味着“我(一个线程)已经拥有锁时,我可以两次或更多次获得锁”。
void test()
{
  std::timed_mutex m;
  std::unique_lock<decltype(m)> lk(m, std::defer_lock);

  // acquire lock
  lk.lock();
  // You can query locked status via unique_lock object
  std::cout << "Do I have own lock? " << lk.owns_lock() << std::endl;
  // release lock
  lk.unlock();
}

3
+1 答案正确但引用错误。30.4.1.3.1 [thread.timedmutex.class]/p3/b2:拥有timed_mutex对象的线程在该对象上调用lock()、try_lock()、try_lock_for()或try_lock_until()方法。 - Howard Hinnant
在这种情况下,我认为我有另一个问题,即我要如何“解决这个问题”或使它按照我想要的方式运行,我应该发表另一个问题还是编辑此问题以包括它?我应该使用递归互斥锁吗? - lfxgroove

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接