进程等待互斥锁

Process while waiting for mutex lock

本文关键字:等待 进程      更新时间:2023-10-16

是否有办法在等待互斥锁时执行代码段?

唯一真正影响应用程序性能的内部因素是数据库交互,有时我需要严格的同步,因为数据库交互可能会导致争用,所以我希望使用等待锁从数据库获取数据的时间。

例如,我希望代码看起来像这样,在pseudo:

boost::unique_lock<boost::mutex> process_lock(process_mutex, work_while_contending);
//code to execute while lock contending
process_lock.proceed_after_lock();

我已经检查了boost的同步部分,虽然futuresrecursive听起来像我的意图可以实现,但我不知道如何实现我的意图。

如何实现我的意图?

在大多数情况下,您并不想这样做。如果你想这样做,你可能想使用期货,像这样:

auto f = std::async(std::launch::async, [&]() {
   // do work in another thread here.
});
boost::unique_lock<boost::mutex> process_lock(process_mutex);
auto result = f.get();
// proceed here the work is done and you have the lock

…这允许您在另一个线程中工作,而原始线程正在等待互斥锁。一旦工作完成并获得互斥锁,线程就会继续。如果在获得互斥锁之前工作完成,那么工作线程将离开,原始线程将空闲等待互斥锁。

为什么你不想这样做:如果你在工作完成之前获取互斥锁,那么没有其他线程能够获取互斥锁,程序将在等待"后台"工作完成时停止。

一个可能的解决方案是使用一个非阻塞try_lock的忙碌等待循环。这里的潜在问题是线程没有等待互斥锁,因此不能保证线程会获得互斥锁。如果有很多人在争夺它,而其他人在积极等待,那么你永远不会得到它。如果您等待它,那么操作系统通常会保证某种顺序,以便您最终获得它。如果你不等待,就无法保证。

这其实很简单。对于请求延迟互斥锁上的实际锁的锁,您可以调用另一个构造函数。然后可以调用try_lock()方法来尝试获取锁,这是一个非阻塞调用,返回一个布尔值,指示锁是否被成功获取。在您的情况下,您可以像这样使用这个方法:

boost::unique_lock<boost::mutex> process_lock(process_mutex, boost::defer_lock_t);
while(!process_lock.try_lock())
{
    ...do some work
}

一旦互斥锁被锁成功获取,它将像往常一样负责再次解锁它,因此您没有引入任何异常处理问题。

EDIT:刚刚对这个问题有了另一个想法。如果每次锁尝试失败时都想运行一个任务,那么我给出的答案是很好的,但是如果您想要做的工作只需要在第一次尝试时获得锁而不能执行一次,那么下面的方法将更合适:

boost::unique_lock<boost::mutex> process_lock(process_mutex, boost::try_to_lock_t);
if(!process_lock.owns_lock())
{
    ...do some work
    process_lock.lock();
}