在等待互斥锁锁定时,有没有办法执行代码段?
我的应用程序性能唯一真正的内部打击是数据库交互,有时我需要严格的同步,因为数据库交互可能会引起争用,所以我想用时间等待锁从数据库中获取数据。
例如,我希望代码看起来像伪:
boost::unique_lock<boost::mutex> process_lock(process_mutex, work_while_contending);
//code to execute while lock contending
process_lock.proceed_after_lock();
我已经检查过提升synchronization section,而futures
和recursive
听起来像我的意图可以实现,但我无法弄清楚如何实现我的意图。
我的意图如何实施?
答案 0 :(得分:3)
在大多数情况下,你真的不想这样做。如果你想这样做,你可能想要使用期货,比如:
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
...这使您可以在原始线程等待互斥锁时在另一个线程中工作。一旦完成工作并获得互斥锁,线程就会继续。如果工作在获取互斥锁之前完成,则工作线程将消失,原始线程将空闲等待互斥锁。
以下是您不想这样做的原因:如果您在工作完成之前获得了互斥锁,那么没有其他线程可以获取互斥锁,程序将在等待&#34;背景&#34;努力完成。
一种可能的解决方案是使用带有非阻塞try_lock
的忙等待循环。这里潜在的问题是线程没有等待互斥锁,所以不能保证线程会得到它。如果有很多争论,而其他人正在积极等待,那么你永远不会得到它。如果你等待它,那么通常操作系统将保证某种顺序,以便你最终得到它。如果您不等待,则无法保证。
答案 1 :(得分:2)
这实际上很容易。您可以调用一个不同的构造函数来锁定请求延迟互斥锁的实际锁定。然后,您可以调用try_lock()方法来尝试获取锁,这是一个非阻塞调用,返回一个布尔值,指示锁是否成功获取。在您的情况下,您可以像这样使用此方法:
boost::unique_lock<boost::mutex> process_lock(process_mutex, boost::defer_lock_t);
while(!process_lock.try_lock())
{
...do some work
}
一旦锁定成功获得互斥锁,就会像正常情况一样再次解锁互斥锁,因此您没有在异常处理方面引入任何问题。
编辑:刚想到这个问题。如果每次锁定尝试失败时都要运行一个任务,我给出的答案很好,但是如果你想要做的工作只需要在第一次尝试时无法获得锁定就完成一次,那么以下方法更合适:
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();
}