zoukankan      html  css  js  c++  java
  • read write spinlock

    发一个自己基于 C++11 写的 read write spinlock,在 MinGW 4.8.2 (gcc 4.8 全面支持c++ 11,但由于gcc windows平台 libstdc++ 目前还不支持 thread,所以用 boost 1.49 及以上版本作为thread库)。

    目前在 Xeon E5606 (4核8线程) Win2008 x64平台上测试通过,但还需要在内存弱序的arm上做进一步测试

    代码 spinlock.cpp

    #include<atomic>
    #include<cassert>
    
    #define SPIN_LOCK_UNLOCK 0
    #define SPIN_LOCK_WRITE_LOCK -1
    
    using std::atomic;
    using std::atomic_int;
    using std::atomic_store_explicit;
    using std::atomic_load_explicit;
    using std::atomic_compare_exchange_weak_explicit;
    using std::memory_order_relaxed;
    using std::memory_order_acquire;
    using std::memory_order_release;
     
    typedef atomic<int> spinlock_t;
    
    void rwlock_init(spinlock_t &l)
    {
        atomic_store_explicit(&l, SPIN_LOCK_UNLOCK, memory_order_relaxed);
    }
    
    void read_lock(spinlock_t &l)
    {
        int expected;
        int desired;
    
        while(true)
        {
            expected = atomic_load_explicit(&l, memory_order_relaxed);
    
            if(expected >= 0)
            {
                desired = 1 + expected;
                if(atomic_compare_exchange_weak_explicit(&l, &expected, desired, memory_order_relaxed, memory_order_relaxed))
                    break; // success
            }
        }
    
        atomic_thread_fence(memory_order_acquire); // sync
    }
    
    void read_unlock(spinlock_t &l)
    {
        int expected;
        int desired;
    
        while(true)
        {
            expected = atomic_load_explicit(&l, memory_order_relaxed);
    
            if(expected > 0)
            {
                desired = expected - 1;
    
                atomic_thread_fence(memory_order_release); // sync
                if(atomic_compare_exchange_weak_explicit(&l, &expected, desired, memory_order_relaxed, memory_order_relaxed))
                    break; // success
            }
            else
            {
                assert(false);
            }
        }
    }
    
    void write_lock(spinlock_t &l)
    {
        int expected;
        int desired;
    
        while(true)
        {
            expected = atomic_load_explicit(&l, memory_order_relaxed);
    
            if(expected == SPIN_LOCK_UNLOCK)
            {
                desired = SPIN_LOCK_WRITE_LOCK;
                if(atomic_compare_exchange_weak_explicit(&l, &expected, desired, memory_order_relaxed, memory_order_relaxed))
                    break; // success
            }
        }
    
        atomic_thread_fence(memory_order_release); // sync
    }
    
    void write_unlock(spinlock_t &l)
    {
        int expected;
        int desired;
    
        while(true)
        {
            expected = atomic_load_explicit(&l, memory_order_relaxed);
    
            if(expected == SPIN_LOCK_WRITE_LOCK)
            {
                desired = SPIN_LOCK_UNLOCK;
    
                atomic_thread_fence(memory_order_release); // sync
                if(atomic_compare_exchange_weak_explicit(&l, &expected, desired, memory_order_relaxed, memory_order_relaxed))
                    break; // success
            }
            else
            {
                assert(false);
            }
        }
    }
    
    //#include<thread>
    #include<boost/thread.hpp>
    #include<iostream>
    
    spinlock_t g_lock;
    long g_total;
    const int count = 5000;
    
    void add_job()
    {
        for(int i = 0; i < count; ++i)
        {
            write_lock(g_lock);
            ++g_total;
            std::cout << "Thread ++ " << boost::this_thread::get_id() << std::endl;
            write_unlock(g_lock);
        }
    }
    
    void read_job()
    {
        for(int i = 0; i < count; ++i)
        {
            read_lock(g_lock);
            std::cout << g_total << std::endl;;
            read_unlock(g_lock);
        }
    }
    
    int main()
    {
        g_total = 0;
        rwlock_init(g_lock);
    
    
        boost::thread th1(add_job);
        boost::thread th2(add_job);
    
        boost::thread th3(read_job);
        boost::thread th4(read_job);
        boost::thread th5(read_job);
    
        th1.join();
        th2.join();
        th3.join();
        th4.join();
        th5.join();
    
        std::cout << "The total: " << g_total << std::endl;
    }

    编译命令行:

    g++  -std=c++11 -Wall -O2 spinlock.cpp -I/d/Sources/boost_1_55_0 -L /d/Sources/boost_1_55_0/stage/lib/ -lboost_thread-mgw48-mt-1_55 -lboost_system-mgw48-mt-1_55

    其它类型 spin lock

    1)最简单(非读写)的 spinlock 可以参考 boost::atomic 里面示例  ;

    2)Linux kernel 中还有一类 write prefer 的spin lock,了解原理后也很容易实现,原理可以参考文档 Linux Kernel Development 3rd。

  • 相关阅读:
    Java框架之SpringMVC
    Java进阶之路
    Java入门基础教学(含配置环境变量等)
    Vue 入门学习
    WCF综合运用之:文件断点续传
    爬取集思录数据(1)--强赎表
    爬虫知识点(一)
    已知1、某股票的增减持日期,2、股票从上市至今的交易数据,求减持后(交易日)1天,5天,15天的收盘价。
    从tushare获取增减持数据
    生成文本序列
  • 原文地址:https://www.cnblogs.com/JesseFang/p/3521282.html
Copyright © 2011-2022 走看看