[英]How do I safely write a test and test-and-set (TATAS) spinlock with C++11 for x86(-64)?
我目前正在研究Spinlock類,並試圖使其盡可能合理,主要是基於以下建議: https : //software.intel.com/zh-cn/articles/implementing-scalable-atomic-locks-for -多核心Intel的EM64T和-IA32架構
正在進行的工作如下所示:
class Spinlock
{
public:
Spinlock() : m_lock(false) {}
void lock()
{
// heavy test here for the usual uncontested case
bool exp = false;
if (!m_lock.compare_exchange_weak(exp, true, std::memory_order_acquire))
{
int failCount = 0;
for (;;)
{
// processor spin loop hint
_mm_pause();
// spin on mov instead of lock instruction
if (!m_lock.load(std::memory_order_relaxed))
{
// heavy test now that we suspect success
exp = false;
if (m_lock.compare_exchange_weak(exp, true, std::memory_order_acquire))
{
return;
}
}
// backoff (potentially make exponential later)
if (++failCount == SOME_VALUE)
{
// Yield somehow.
failCount = 0;
}
}
}
}
void unlock()
{
m_lock.store(false, std::memory_order_release);
}
std::atomic_bool m_lock;
};
但是,從那里輕松地讀取內容似乎可以從理論上允許生成的代碼做意外的事情,例如創建死鎖: http : //joeduffyblog.com/2009/02/23/the-magical-dueling-deadlocking-spin-locks/
這段代碼不應像鏈接示例那樣陷入僵局,因為外部獲取應該防止松弛的負載向后移動,但是我實際上並沒有處理所有可能存在的代碼轉換。 我需要什么存儲順序和/或防護來確保此代碼安全而不丟失性能? 因為周圍的內存順序過於寬松,退回實現是否有可能比預期的發生更多或更少的頻繁(>幾次循環)?
在相關說明中,為什么網絡上的自旋鎖示例對自旋鎖使用獲取/釋放內存順序而不是順序一致? 我發現有一條評論說,允許自旋鎖發布越過以后的自旋鎖獲取可能導致問題: http : //preshing.com/20120913/acquire-and-release-semantics/#IDComment721195810
這段代碼不應像鏈接示例那樣陷入僵局,因為外部獲取應該防止松弛的負載向后移動,但是我實際上並沒有處理所有可能存在的代碼轉換。
獲取操作保證編譯器和CPU都不會在獲取操作之前對后續的讀取進行重新排序。
我需要什么存儲順序和/或防護來確保此代碼安全而不丟失性能?
您在這里不需要任何額外的同步,您的代碼可以完成正確的事情。
為什么網絡上的自旋鎖示例使用自旋鎖的獲取/釋放內存順序而不是順序一致?
因為獲取/釋放語義足以實現互斥體。 在某些體系結構上,順序一致性操作比獲取/發布更為昂貴。
我不建議您看足夠多的atomic <>武器:C ++內存模型和現代硬件 ,它非常詳細地介紹了此主題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.