自旋锁定堆栈和内存屏障(C++)
Spin locked stack and memory barriers (C++)
我有一个实现旋转锁:
class Spinlock {
public:
void Lock() {
while (true) {
if (!_lock.test_and_set(std::memory_order_acquire)) {
return;
}
}
}
void Unlock() {
_lock.clear(std::memory_order_release);
}
private:
std::atomic_flag _lock;
};
我在中使用SpinLock类
class SpinlockedStack {
public:
SpinlockedStack() : _head(nullptr) {
}
~SpinlockedStack() {
while (_head != nullptr) {
Node* node = _head->Next;
delete _head;
_head = node;
}
}
void Push(int value) {
_lock.Lock();
_head = new Node(value, _head);
_lock.Unlock();
}
bool TryPop(int& value) {
_lock.Lock();
if (_head == nullptr) {
value = NULL;
_lock.Unlock();
return false;
}
Node* node = _head;
value = node->Value;
_head = node->Next;
delete node;
_lock.Unlock();
return true;
}
private:
struct Node {
int Value;
Node* Next;
Node(int value, Node* next) : Value(value), Next(next) {
}
};
Node* _head;
Spinlock _lock;
};
我明白我应该设置记忆障碍。我可以使用原子变量:
struct Node {
int Value;
std::atomic<Node*> Next;
Node(int value) : Value(value) {
}
};
std::atomic<Node*> _head;
Spinlock _lock;
...
void Push(int value) {
_lock.Lock();
Node* currentHead = _head.load(std::memory_order_acquire);
Node* newHead = new Node(value);
newHead->Next.store(currentHead, std::memory_order_relaxed);
_head.store(newHead, std::memory_order_release);
_lock.Unlock();
}
bool TryPop(int& value) {
_lock.Lock();
Node* currentHead = _head.load(std::memory_order_acquire);
if (currentHead == nullptr) {
value = NULL;
_lock.Unlock();
return false;
}
value = currentHead->Value;
_head.store(currentHead->Next.load(std::memory_order_relaxed), std::memory_order_release);
delete currentHead;
_lock.Unlock();
return true;
}
我还可以使用atomic_thread_fence():
struct Node {
int Value;
Node* Next;
Node(int value) : Value(value) {
}
};
Node* _head;
Spinlock _lock;
...
void Push(int value) {
_lock.Lock();
Node* currentHead = _head;
std::atomic_thread_fence(std::memory_order_acquire);
Node* newHead = new Node(value);
newHead->Next = currentHead;
std::atomic_thread_fence(std::memory_order_release);
_head = newHead;
_lock.Unlock();
}
bool TryPop(int& value) {
_lock.Lock();
std::atomic_thread_fence(std::memory_order_acquire);
Node* currentHead = _head;
if (currentHead == nullptr) {
value = NULL;
_lock.Unlock();
return false;
}
value = currentHead->Value;
std::atomic_thread_fence(std::memory_order_acquire);
Node* nextNead = currentHead->Next;
std::atomic_thread_fence(std::memory_order_release);
_head = nextNead;
delete currentHead;
_lock.Unlock();
return true;
}
我的问题:
- 我会设置记忆障碍吗
- 在这种情况下,使用什么更好(原子变量或atomic_thread_fence)?为什么
锁的获取已经建立了所需的内存保证。
当线程释放锁时,它必须写入原子标志。这保证了当下一个线程获取锁并看到对标志的写入时,获取线程保证看到释放线程在写入标志之前所做的所有写入。
顺便说一句,你应该使用类似RAII的东西来确保你的锁在任何情况下都被释放。
此外,您必须使用ATOMIC_FLAG_INIT初始化您的锁,否则它将处于未定义状态。
相关文章:
- 将字符串存储在c++中的稳定内存中
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- Win32编译器选项和内存分配
- 当vector是tje全局变量时,c++中vector的内存管理
- 带内存和隔离功能的SQLite
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 迭代时从向量和内存中删除对象
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 为什么示例代码访问IUnknown中已删除的内存
- 如何在C++类内存结构中创建"spacer"?
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 类型总是使用其大小存储在内存中吗
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存