std :: unique_lock :: try_lock_until()忙等吗?

时间:2015-07-31 15:36:28

标签: c++ multithreading c++11 locking

我正在考虑使用以下代码:

auto now = std::chrono::high_resolution_clock::now();

std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
if(lock.try_lock_until(now + std::chrono::milliseconds(15))
{
    // swap some buffer pointers...
    lock.unlock();
}

但是,从文档中我不清楚如果将try_lock_until()实现为忙等待,或者线程将在尝试之间产生/睡眠(这是我想要的行为)。这是在最小化线程资源使用的同时查询锁的最佳方法吗?

1 个答案:

答案 0 :(得分:2)

The CppReference page for std::unique_lock::try_lock_until indeed only states it "Blocks until specified timeout_time has been reached or the lock is acquired". This is not just a shortcoming of the website though. The standard (I used the November 2014 working draft) carefully steers clear of specifying whether a thread has to yield while blocking on any kind of mutex, talking only about acquiring ownership.

For std::mutex, for instance, section 30.4.1.2.1 states

If one thread owns a mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock()) until the owning thread has released ownership with a call to unlock().

No mention of scheduling or yielding is made at all, though.

Furthermore, even if it did mention yield explicitly, that wouldn't help that much, as this_thread::yield (section 30.3.2) merely "Offers the implementation the opportunity to reschedule".

CppReference makes this more concrete, stating

The exact behavior of this function depends on the implementation, in particular on the mechanics of the OS scheduler in use and the state of the system. For example, a first-in-first-out realtime scheduler (SCHED_FIFO in Linux) would suspend the current thread and put it on the back of the queue of the same-priority threads that are ready to run (and if there are no other threads at the same priority, yield has no effect).

So I'm afraid the question of how try_lock_until is implemented in C++ cannot be answered. Perhaps you can ask a new question targeting a specific platform. For your second question ("Is this the best way to query a lock while minimizing thread resource usage?") the answer is yes, the best option your platform offers should be invoked using this API (though, as T.C. commented, try_lock_for seems like a better fit).