c++ - boost upgrade_lock 和 DCLP(双重检查锁定模式)

标签 c++ multithreading boost locking double-checked-locking

假设我们有以下(伪)代码:

using UpgradeLock = boost::upgrade_lock<boost::shared_mutex>;
using UpgradeToUniqueLock = boost::upgrade_to_unique_lock<boost::shared_mutex>;

boost::shared_mutex mtx;

void DeleteTable(<tbl>) {
  UpgradeLock lock(mtx);
  if (<the table exists>) {
    UpgradeToUniqueLock up(lock); // (!)
    // delete the table
  }
}

假设两个线程刚刚进入这个函数并且都到达了语句,标记为(!)

我不知道接下来会发生什么。我有以下选择:

  1. 在第二个线程释放其 UpgradeLock 之前,一个线程无法获得独占访问权,但在它也获得独占访问权之前也无法获得独占访问权。死锁。
  2. 一个线程获得了独占访问权,而另一个线程在带有标记 (!) 的行处被挂起。

我想第二个选项可能会发生什么,但在这种情况下,即使有锁定的环境,我们也必须重新检查我们的数据没有被“外部”更改,即我们必须使用臭名昭著的 DCLP。我说得对吗?

我还没有找到任何关于它的合理信息,所以不要怪我太多:)

最佳答案

如果我理解正确,那么数字 2 将会发生。

如果您使用 Reader/Writer Locks您必须遵守假设的协议(protocol),只要多个读者共享锁,他们就只能进行读取访问。如果他们需要获得一些写权限,他们必须升级锁。

现在在你的情况下,可能会发生多个线程进入 if 语句并等待获取锁。没错,他们都会一个接一个地拿到锁。问题是,在获取锁之后,另一个线程可能已经删除了表。

这就是您可能需要双重检查锁定模式的原因。

从这里您有多种选择:

选项 1: 检查表是否指向 NULL 并且什么都不做

选项 2: 如果在调用 delete 之后指针设置为 NULLnullptr,只需再次调用 delete C++ 即可那(如果 delete 来自标准库)=> 什么都不做。仅供引用阅读:

http://en.cppreference.com/w/cpp/language/delete

if expression evaluates to a null pointer value, no destructors are called, and the deallocation function is not called.

  UpgradeLock lock(mtx);

  if (<the table exists>) 
  {
     UpgradeToUniqueLock up(lock); // (!)
     if(<table still exists>)
     {
       // delete the table
       // and set the pointer to nullptr
     }
   } 

但根据选项 2,如果 delete 由 STL 实现,则以下代码片段就可以了: UpgradeLock 锁(mtx);

  if (<the table exists>) 
  {
     UpgradeToUniqueLock up(lock); // (!)   
     // delete the table
     // and set the pointer to nullptr

  } 

选项 3: 请改用 std::shared_ptrboost::shared_ptr。它们是同步的。因此,您甚至不需要锁,只需从多个线程调用 ptr.reset() 即可。

关于c++ - boost upgrade_lock 和 DCLP(双重检查锁定模式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47264045/

相关文章:

c++ - 如何从 RE2 检索完整的正则表达式匹配?

c++ - Recursive Permutation、Ellis Horowitz 算法和数据结构混淆。

c++ - static const 和 constexpr 变量有什么区别?

c++ - 在 Visual Studio 2008 中链接 libav 库

c# - 让用户选择他想要多少个线程?

java - TIMEr 在 java 中无法正常工作

c++ - 父线程join() : Blocks Until Children Finish?

c++ - 围绕 Boost Graph 库中的捆绑属性进行设计

python - C++ Boost Python numpy 数组初始化

c++ - boost::spirit::karma 语法:带有可选属性的结构的逗号分隔输出