简体   繁体   English

等待互斥锁时处理

[英]Process while waiting for mutex lock

Is there some way to execute a code section while waiting for a mutex to lock? 在等待互斥锁锁定时,有什么方法可以执行代码段吗?

The only true internal hit to my application's performance is database interaction, and there are times where I need strict synchronization which because of the database interaction may cause contention, so I'd like to use the time waiting for a lock to get data from the database. 对我的应用程序性能的唯一真正的内部打击是数据库交互,在某些情况下我需要严格的同步,由于数据库交互可能导致争用,因此我想花时间等待锁来从数据库中获取数据。数据库。

For example, I'd like the code to look something like, in pseudo: 例如,我希望代码看起来像是伪的:

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

I've examined boost's synchronization section , and while futures and recursive sound like my intent could be achieved, but I can't figure out how to implement my intent. 我已经检查了boost的同步部分 ,虽然可以实现像我的意图之类的futuresrecursive声音,但是我不知道如何实现我的意图。

How can my intent be implemented? 我的意图如何实现?

You don't really want to do this in most cases. 在大多数情况下,您实际上并不想这样做。 If you do want to do it, you probably want to use futures, like this: 如果确实要这样做,则可能要使用期货,如下所示:

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

... This lets you do work in another thread while the original thread is waiting for the mutex. ...这使您可以在原始线程正在等待互斥时在另一个线程中工作。 Once both the work is complete and the mutex is acquired the thread continues. 一旦完成工作并获取了互斥锁,线程就会继续。 If the work finishes before the mutex is acquired then the work thread will go away and the original thread will just be idle waiting for the mutex. 如果在获取互斥锁之前完成工作,则工作线程将消失,原始线程将处于空闲状态,等待互斥锁。

Here's why you don't want to do this: If you acquire the mutex before the work completes then no other thread will be able to acquire the mutex, the program will stall while it waits for the "background" work to complete. 这就是为什么您不想要这样做的原因:如果您在工作完成之前获取了互斥锁,则其他线程将无法获取该互斥锁,程序将在等待“后台”工作完成时停止运行。

A possible solution is to use a busy wait loop with a non-blocking try_lock . 可能的解决方案是使用带有非阻塞try_lock的繁忙等待循环。 The potential problem here is that the thread is not waiting for the mutex, so there is no guarantee that the thread will ever get ahold of it. 这里的潜在问题是线程不等待互斥体,因此无法保证线程将永远获得互斥体。 If there is a lot of contention for it, and others are actively waiting, then you'll never get it. 如果有很多争论,而其他人都在积极等待,那么您将永远无法解决。 If you wait for it, then typically the OS will guarantee some sort of order such that you will eventually get it. 如果您等待它,那么操作系统通常会保证某种顺序,以便您最终将其获得。 If you're not waiting, that guarantee cannot be made. 如果您不等待,则无法保证。

This is actually very easy. 这实际上很容易。 There's a different constructor you can call for the lock that requests the actual lock on the mutex to be deferred. 您可以调用一个不同的构造函数,以请求将互斥量上的实际锁定推迟。 You can then call the try_lock() method to attempt to obtain the lock, which is a non-blocking call that returns a boolean indicating whether the lock was successfully taken or not. 然后,您可以调用try_lock()方法来尝试获取锁,这是一个非阻塞调用,它返回一个布尔值,指示是否成功获取了该锁。 In your case, you could use this method like so: 在您的情况下,可以这样使用此方法:

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

Once the mutex is successfully obtained by the lock, it will take responsibility for unlocking it again like normal, so you haven't introduced any problems with exception handling. 一旦锁成功获得了互斥锁,它将负责像往常一样再次对其进行解锁,因此您不会在异常处理方面引入任何问题。

EDIT : Just had another thought about this question. 编辑 :刚刚对此问题有另一个想法。 The answer I gave is great if there's a task you want to run each time a lock attempt fails, but if the work you wanted to do only needed to be done a single time if the lock could not be obtained on the first try, the following approach would be more suitable: 如果每次锁尝试失败时都有一个您想运行的任务,那么我给出的答案很好,但是如果您想要做的工作只需要完成一次,而第一次尝试却无法获得锁,那么我给出的答案就很好。以下方法将更适合:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM