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++标准库多线程的程序员有所启示。

  • 相关阅读:
    Union all 分别排序
    GridView中显示bool字段(在数据库中是字符类型)
    oracle语句有关知识
    验证控件验证DropDownList
    【Java高级工程师蜕变之路】013 Spring MVC基础以及高级应用
    【Java高级工程师蜕变之路】012 Spring AOP源码分析
    【Java高级工程师蜕变之路】010 Spring IOC的应用
    【Java高级工程师蜕变之路】017 Spring Data JPA的应用与源码剖析
    【Java高级工程师蜕变之路】009 手写IOC和AOP
    【Java高级工程师蜕变之路】015 Spring MVC源码剖析
  • 原文地址:https://www.cnblogs.com/albizzia/p/8550093.html
Copyright © 2011-2022 走看看