Boost upgrade_lock和DCLP(双重检查锁定模式)
Boost upgrade_lock and DCLP (double-checked locking pattern)
假设我们有以下(伪)代码:
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
}
}
假设两个线程刚刚进入这个函数,并且都到达了用(!)
标记的语句。
我不知道到时会发生什么。我有以下选项:
- 一个线程在第二个线程释放其
UpgradeLock
之前不能获得独占访问,但在获得独占访问之前也不能。僵局 - 一个线程获得独占访问,而另一个线程在标记为
(!)
的行处被挂起
我想第二种选择可能会发生,但在这种情况下,即使锁定了环境,我们也必须重新检查我们的数据是否在"外部"更改,即我们必须使用臭名昭著的DCLP。我说得对吗?
我还没有找到任何可信的信息,所以不要责怪我:)
如果我正确理解你,那么数字2就会发生。
如果您使用读写器锁,则必须遵守协议,该协议假定,只要多个读写器共享锁,它们就只能进行读取访问。如果他们需要获得一些写入权限,他们必须升级锁。
现在,在您的情况下,可能会发生多个线程进入if
-语句并等待锁定获取的情况。这是真的,他们都会一个接一个地得到锁。问题是,在获取锁之后,可能会发生另一个线程已经delete
访问该表的情况。
这就是为什么您可能需要双重检查的锁定模式。
从这里你有多种选择:
选项1:检查表是否指向NULL
并且不执行
选项2:只要再次调用delete
,如果在调用delete
之后指针被设置为NULL
或nullptr
,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,如果CCD_ 12由STL实现UpgradeLock锁(mtx);
if (<the table exists>)
{
UpgradeToUniqueLock up(lock); // (!)
// delete the table
// and set the pointer to nullptr
}
选项3:请改用std::shared_ptr
或boost::shared_ptr
。它们是同步的。所以您甚至不需要锁,只需从多个线程调用ptr.reset()
即可。
- 如何检查线程是否锁定
- 仔细检查锁定问题,c++
- 通过检查条件并重新检查来获取锁定
- Boost upgrade_lock和DCLP(双重检查锁定模式)
- 双重检查和锁定模式在c++(而不是11)中有效吗
- 我的双重检查锁定模式实现是否正确?
- mutex::lock() 检查一次解锁状态是否已经被另一个线程锁定?
- C++与双重检查锁定的危险:变通方法
- C++11:对延迟初始化进行安全的双重检查锁定.可能的
- C++:检查计算机是否已锁定
- 这是否可以兑换线程安全的双重检查锁定模式
- 双重检查共享指针的锁定
- 仔细检查锁定值变为空
- 通过双重检查锁定模式实现call_once
- 线程安全惰性初始化:静态vs std::call_once vs双重检查锁定
- 这是双重检查锁定的有效替代方案吗
- 这个解决方案对MSVC的双重检查锁定错误和函数静态有什么问题?
- c++ 11中的双重检查锁定
- 为双重检查锁定提供适当的编译器内在特性
- 这是正确的 C++11 双检查锁定shared_ptr版本吗?