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

try_lock問題は、 falseを返しても、test()がまったくブロックしないことです。私が見落としているものがありますか、これはgccのバグですか、それとも次にどこに行って何が問題なのかを調べる必要がありますか?アドバイスと助けてくれてありがとう!

私はこの小さなプログラムを次のようにコンパイルしました:g++ -pthread -std=c++11 threads.cpp -o threads そしてそれが助けになるなら、これはgccと私のOSのバージョンです:

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
4

1 に答える 1

6

コードの動作は未定義です。非再帰的な所有権セマンティクスstd::timed_mutexがあります。同じスレッドで2回目にロック(try_lockファミリーを含む)を取得することは禁止されています。

C++11標準30.4.1.3.1[thread.timedmutex.class]/ p3 / b2 :(ハワード・ヒナントに感謝)

3プログラムの動作は、次の場合は未定義です。

  • オブジェクトを所有するスレッドは、、、、またはそのオブジェクト上で、またはをtimed_mutex呼び出しますlock()try_lock()try_lock_for()try_lock_until()

C++11標準30.4.1.2[thread.mutex.requirements.mutex]/ p6-7:


編集:

どのように「これを回避」するのか、それとも私が望むように動作させるのか?代わりに再帰ミューテックスを使用する必要がありますか?

一般的に、例外の安全性を考慮して、mutexオブジェクトのロックを取得/解放することはお勧めしません。unique_lock代わりにオブジェクトを使用する場合は、owns_lock()メンバー関数が役立つ場合があります。一方、recursive-mutexは、「再帰的」とは「私がすでにロックを所有している場合、I(スレッド)が2回以上ロックを取得できる」ことを意味するため、目的には役立ちません。

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();
}
于 2013-01-21T02:11:14.697 に答える