【问题标题】:Safely skip an task if mutex is locked如果互斥锁被锁定,安全地跳过任务
【发布时间】:2020-05-17 19:07:50
【问题描述】:

我正在努力解决互斥锁/锁的问题。 情况:

  • 任务 A 需要相对较长的时间。它在一个线程中不规则地执行(但一次只执行一次)。
  • 有一个任务 B,它很快,并且经常从另一个线程调用。
  • 两个任务都在同一个内存上工作,因此不应同时执行。
  • 任务 B 不等待任务 A 至关重要,因为上下文是在渲染后与 GPU 通信(纹理传输),这会导致帧延迟,因为任务 A 可能需要几个帧。
  • 如果任务 A 当前正在运行,则应该跳过任务 B。
  • 但决不能跳过任务 A

到目前为止我所拥有的: 任务 A 的线程(不定期调用):

{
  std::unique_lock<std::mutex> mlock(the_mutex);
  TaskA();
}

还有任务B(挂在渲染线程中)

{
  if mutex.try_lock()
  {
    TaskB();
    the_mutex.unlock();
  }
}

The_mutex 是对象的通用 std::mutex。

这一次真的那么容易,还是我错过了什么?在过去烦人的多线程错误之后,我对这个话题变得不安全。 非常感谢。

【问题讨论】:

  • 抽象不是很好吗? :)

标签: c++ multithreading mutex


【解决方案1】:

您的代码是正确的,但为了异常安全和防止资源泄漏,您最好在任务 B 中使用 RAII。一般规则是“使用 RAII 锁守卫(lock_guard、unique_lock、shared_lock),永远不要调用 mutex.lock 和mutex.unlock 直接 (RAII)"。

std::unique_lock<std::mutex> mlock(the_mutex, std::defer_lock);
if (mlock.try_lock()) {
    TaskB();
}

std::unique_lock<std::mutex> mlock(the_mutex, std::try_to_lock);
if (mlock) {
    TaskB();
}

【讨论】:

  • 也可以使用std::try_lock 代替std::defer_lock 然后只使用if (mlock)
  • @AlanBirtles std::try_lock没有使用RAII,需要mutex::unlock,所以不如直接使用mutex::lock
  • 不知道为什么你认为std::try_lockstd::defer_lock 有任何不同,如果en.cppreference.com/w/cpp/thread/unique_lock/unique_lock 有区别,那std::unique_lock 就毫无意义了
  • @AlanBirtles 查看en.cppreference.com/w/cpp/thread/try_lock 上的示例代码,在std::try_lock 之后需要mutex::unlockunique_lock 不是这种情况,您不需要 unlock,因为析构函数会为您执行此操作。
  • 对不起,我的意思是try_to_lock
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
相关资源
最近更新 更多