zoukankan      html  css  js  c++  java
  • 通过atomic_flag简单自旋锁实现简单说明标准库中锁使用的memory_order

    在使用标准库中的加锁机制时,例如我们使用std::mutex,写了如下的代码(下面的代码使用condition_variable可能更合适)

    std::mutex g_mtx;
    int g_resNum;
    // and how to get the resource
    ...
    
    // 线程1使用如下代码:
    {
        std::lock_guard<std::mutex> guard(g_mtx);
        // prepare the resource
        ...
        // set the resource num
        g_resNum = ...;
    }
    
    // 线程2使用如下的代码:
    {
        std::lock_guard<std::mutex> guard(g_mtx);
        // check the g_resNum
        if (g_resNum > 0)
        {
            ...
        }
    }

     我们知道如果先运行线程1的代码,也就是说线程1获得了锁,进行了准备资源的操作。然后运行线程2,也就是说线程2之后获得了锁,可以知道线程1加锁区域的代码已经执行完毕,而且对线程2可见,我们可以放心的使用线程1中设置的资源。这里面的原因是

    标准库在实现std::mutex过程中使用了memory_order。http://en.cppreference.com/w/cpp/atomic/memory_order 中的描述如下:

    Acquire operation
    Atomic load with memory_order_acquire or stronger is an acquire operation. The lock() operation on a Mutex is also an acquire operation. 

    Release operation
    Atomic store with memory_order_release or stronger is a release operation. The unlock() operation on a Mutex is also a release operation. 

    C++ atomic中对Acquire- Release ordering的简单介绍如下:

    If an atomic store in thread A is tagged memory_order_release and an atomic load in thread B from the same variable is tagged memory_order_acquire, all memory writes (non-atomic and relaxed atomic) that happened-before the atomic store from the point of view of thread A, become visible side-effects in thread B, that is, once the atomic load is completed, thread B is guaranteed to see everything thread A wrote to memory.

    关于memory_order的简单介绍就到这里,下面我用一个很简单的spinlock的实现来简单说明一下memory_order的使用:

    class spinlock_mutex
    {
        std::atomic_flag flag;
    public:
        spinlock_mutex() :
            flag(ATOMIC_FLAG_INIT)
        {}
    
        void lock()
        {
            while(flag.test_and_set(std::memory_order_acquire));
        }
    
        bool try_lock()
        {
            if (flag.test_and_set(std::memory_order_acquire))
                return false;
    
            return true;
        }
    
        void unlock()
        {
            flag.clear(std::memory_order_release);
        }
    };

    上述spinlock实现存在性能上的问题,网上有关于这个实现问题的讨论,参考网址:https://www.zhihu.com/question/55764216

    希望能给初学C++标准库多线程的程序员有所启示。

  • 相关阅读:
    C++ 引用详解
    QT的UDP组播技术
    idea快捷键
    window10安装不同版本的mysql(5.7和8.0.25)
    第2篇scrum
    结对项目:四则运算(C语言)
    个人项目wc(C语言)
    修改博客园背景,css
    第一次作业
    第4篇 Scrum 冲刺博客(专✌️团队)
  • 原文地址:https://www.cnblogs.com/albizzia/p/8550093.html
Copyright © 2011-2022 走看看