C++11 递归自旋锁实现
C++11 Recursive Spinlock Implementation
在这篇代码审查文章之后,我尝试实现递归旋转锁,如下所示。
class SpinLock {
public:
SpinLock() : lock_owner(lock_is_free), lock_count(0) {
}
inline bool tryLock() {
if (lock_owner != std::this_thread::get_id()) {
bool locked = lock_owner.compare_exchange_strong(lock_is_free,
std::this_thread::get_id(), std::memory_order_acquire,
std::memory_order_relaxed);
if (locked) {
lock_count++;
}
return locked;
}
lock_count++;
return true;
}
inline void lock() {
if (lock_owner != std::this_thread::get_id()) {
while(!lock_owner.compare_exchange_weak(lock_is_free,
std::this_thread::get_id(), std::memory_order_acquire,
std::memory_order_relaxed));
assert(lock_owner == std::this_thread::get_id());
} else {
printf("Recursive lockingn");
}
lock_count++;
}
inline void unlock() {
assert(lock_owner == std::this_thread::get_id());
assert(lock_count != 0);
--lock_count;
if (lock_count == 0) {
lock_owner.store(lock_is_free, std::memory_order_release);
}
}
inline bool isOwner() {
return lock_owner == std::this_thread::get_id();
}
inline bool isSet() {
return lock_owner != lock_is_free;
}
private:
std::thread::id lock_is_free;
std::atomic<std::thread::id> lock_owner;
int lock_count;
};
但是当我尝试使用多个线程锁定时,锁定方法似乎并不能确保相互排斥。我在这里做错了什么?
正如注释中指出的,如果条件为 false,compare_exchange_weak
替换第一个参数的内容,因此lock_is_free
已损坏。
此外,这不是有效的代码,因为compare_exchange_weak
按位顺序比较存储在atomic
变量中的对象的值,因此就好像它们是使用std::memcmp
进行比较一样。 并且类型std::thread::id
的对象不是整型类型,并且具有用于比较的特殊重载。pthread_t
也是如此(pthread_equal
),所以本质上你依赖于实现定义的行为。
您可以通过运行以下代码来确认这一点
#include <type_traits>
#include <iostream>
#include <thread>
#include <pthread.h>
using std::cout;
using std::endl;
int main() {
cout << std::boolalpha << std::is_integral<std::thread::id>::value << endl;
cout << std::boolalpha << std::is_integral<decltype(pthread_self())>::value
<< endl;
return 0;
}
在这种情况下,为什么不直接重载memcpy
并memcmp
与std::thread::id
一起工作呢? cpp首选项和 cplusplus.com 都确认没有保证。 甚至重载memcpy
(全局和std
命名空间)在我的系统上使用我的标准库也不起作用。 我怀疑它不会在大多数其他系统(标准库和编译器组合)上也是如此,原因有两个:
compare_exchange_weak
可能不会在引擎盖下使用memcpy
或memcmp
,并且可能会自行实现- 尽管在将指针传递给
memcpy
之前不需要将指针转换为void*
,但无论如何memcmp
可能会选择默认实现
,但这是不正确的
请参阅下面的代码,了解我在第二点中的意思
void func(void*) {
cout << "void*" << endl;
}
void func(int*) {
cout << "int*" << endl;
}
int main() {
int a = 1;
func(&a);
func(reinterpret_cast<void*>(a));
return 0;
}
要回答您的问题,将compare_exchange_weak
与std::thread::id
一起使用是不正确的("不可移植"可能更好)代码。
相关文章:
- 如何在BST的这个简单递归实现中消除警告
- 使用非递归插入方法实现 AVL 树
- C++ 模板使用递归实现循环
- 了解使用堆栈实现队列的递归调用机制
- 在int main()[c++]中实现一个递归函数
- 链表中的递归长度函数实现
- 递归合并排序算法实现
- 我如何实现递归函数的模板,该模板允许C 中的许多不确定数据类型的参数
- 实现递归函数,避免由 C++ 中 include 的循环调用(没有 #pragma 一次)引起的无限循环输入
- 我应该如何实现递归方法以找到在C++中形成最大堆的多种方法
- 在C++中树的递归实现中少出现1个节点
- 使用递归实现 pow(A, B) % C,其中 A、B 和 C 是正整数
- C++11 递归自旋锁实现
- 在C++中使用OpenMP实现递归函数的并行化
- 如何实现递归"using"/提取模板参数
- 如何在TensorFlow中实现递归神经网络
- 如何在 Windows 上仅使用事件和联锁原语实现递归锁
- 在 C++11 中实现递归代理模式
- 下面使用Map和Vector实现递归级阶遍历的时间复杂度是多少
- 基于Korf 1992的c++实现递归最佳优先搜索的问题