非线程安全的缓存示例:class C {public: C(int param) : m_param(param) {} getValue() { if (!m_alreadyCalculated) { m_val = calculate(m_param); m_alreadyCalculated = true; } return m_val; } double calculate(int param) { // Some calculation }private: int m_param; double m_val; bool m_alreadyCalculated = false;}解决方案考虑以下内容:class C {public: double getValue() { if (alreadyCalculated == true) return m_val; bool expected = false; if (calculationInProgress.compare_exchange_strong(expected, true)) { m_val = calculate(m_param); alreadyCalculated = true; // calculationInProgress = false; } else { // while (calculationInProgress == true) while (alreadyCalculated == false) ; // spin } return m_val; }private: double m_val; std::atomic<bool> alreadyCalculated {false}; std::atomic<bool> calculationInProgress {false};};实际上并不是无锁的,里面有一个自旋锁.但是我想,如果不想由多个线程运行calculate(),就无法避免这样的锁定. getValue()在这里变得更加复杂,但是重要的部分是,一旦计算出m_val,它将始终在第一个if语句中立即返回. 更新出于性能方面的考虑,最好将整个类都填充到缓存行大小. 更新2原始答案中有一个错误,感谢JVApen指出这一点(带有注释).最好将变量calculationInProgress重命名为calculationHasStarted.此外,请注意,此解决方案假定calculate()不会引发异常.Is there any way in C++11 to implement a lock-free cache for an object, which would be safe to access from multiple threads? The calculation I'm looking to cache isn't super cheap but also isn't super expensive, so requiring a lock would defeat the purpose of caching in my case. IIUC, std::atomic isn't guaranteed to be lock-free.Edit: Since calculate isn't -too- expensive, I actually don't mind if it runs once or twice too many. But I -do- need to make sure all consumers get the correct value. In the naive example below, this isn't guaranteed because due to memory re-ordering it's possible for a thread to get an uninitialized value of m_val since another thread set m_alreadyCalculated to true, but didn't set m_val's value yet.Edit2: The comments below point out that for basic types, std::atomic would probably be lock free. In case it is, what's the correct way in the example below of using C++11's memory ordering to make sure it isn't possible for m_alreadyCalculated to be set to true before m_val's value is set?Non-thread-safe cache example:class C {public: C(int param) : m_param(param) {} getValue() { if (!m_alreadyCalculated) { m_val = calculate(m_param); m_alreadyCalculated = true; } return m_val; } double calculate(int param) { // Some calculation }private: int m_param; double m_val; bool m_alreadyCalculated = false;} 解决方案 Consider something as:class C {public: double getValue() { if (alreadyCalculated == true) return m_val; bool expected = false; if (calculationInProgress.compare_exchange_strong(expected, true)) { m_val = calculate(m_param); alreadyCalculated = true; // calculationInProgress = false; } else { // while (calculationInProgress == true) while (alreadyCalculated == false) ; // spin } return m_val; }private: double m_val; std::atomic<bool> alreadyCalculated {false}; std::atomic<bool> calculationInProgress {false};};It's not in fact lock-free, there is a spin lock inside. But I think you cannot avoid such a lock if you don't want to run calculate() by multiple threads.getValue() gets more complicated here, but the important part is that once m_val is calculated, it will always return immediately in the first if statement.UPDATEFor performance reasons, it might also be a good idea do pad the whole class to a cache line size.UPDATE 2There was a bug in the original answer, thanks JVApen to pointing this out (it's marked by comments). The variable calculationInProgress would be better renamed to something as calculationHasStarted.Also, please note that this solution assumes that calculate() does not throw an exception. 这篇关于C ++ 11中的无锁缓存实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!