【问题标题】:Boost upgrade_lock and DCLP (double-checked locking pattern)Boost upgrade_lock 和 DCLP(双重检查锁定模式)
【发布时间】:2017-11-13 12:08:39
【问题描述】:

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

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。我说的对吗?

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

【问题讨论】:

  • @VTT :我认为这是一个答案,而不是评论。

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


【解决方案1】:

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

如果您使用Reader/Writer Locks,您必须遵守协议,该协议假定只要多个读取器共享锁,就只允许他们进行读取访问。如果他们需要获得一些写权限,他们必须升级锁。

现在,在您的情况下,可能会发生多个线程进入if-statement 并等待获取锁的情况。这是真的,他们都会一个接一个地得到锁。问题是,在获得锁之后,可能会发生另一个线程已经delete-ed 表。

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

从这里您有多种选择:

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

选项 2: 只需再次调用delete,如果在调用delete 之后指针设置为NULLnullptr,C++ 就可以了(如果delete 来自标准库)=> 并且什么也不做。仅供参考阅读:

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

如果表达式的计算结果为空指针值,则不调用析构函数,也不调用释放函数。

  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 实现,则以下 sn-p 就可以了: 升级锁锁(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()就可以了。

【讨论】:

  • 感谢您的回答,但结果却有所不同。我不知道,但是只有一个线程可以获取UpgradeLock,所以我上面描述的情况根本不可能发生。见:boost.org/doc/libs/1_44_0/doc/html/thread/…
  • @Alexey 你是对的。这是一个非常优雅的解决方案。我会更正我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多