c++中的原子操作


1. c/c++標准中沒有定義任何操作符為原子的,操作符是否原子和平台及編譯器版本有關

2. GCC提供了一組內建的原子操作,這些操作是以函數的形式提供的,這些函數不需要引用任何頭文件

  2.1 對變量做某種操作,並且返回操作前的值,總共6個函數:

    type __sync_fetch_and_add (type *ptr, type value, ...)    加減運算 相當於  tmp = *ptr;  *ptr += value; return tmp;

    type __sync_fetch_and_sub (type *ptr, type value, ...)    加減運算 相當於  tmp = *ptr;  *ptr -= value; return tmp;

    type __sync_fetch_and_or (type *ptr, type value, ...)       邏輯運算 相當於  tmp = *ptr;  *ptr |= value; return tmp;

    type __sync_fetch_and_and (type *ptr, type value, ...)     邏輯運算 相當於  tmp = *ptr;  *ptr &= value; return tmp;

    type __sync_fetch_and_xor (type *ptr, type value, ...)     位運算 相當於  tmp = *ptr;  *ptr ^= value; return tmp;

    type __sync_fetch_and_nand (type *ptr, type value, ...)   位運算 相當於  tmp = *ptr; *ptr = ~(tmp & value); return tmp;

           注意,__sync_fetch_and_nand在GCC的4.4版本之前語義並非如此,而是 tmp = *ptr; *ptr = ~tmp & value; return tmp;

  2.2 對變量做某種操作,並且返回操作后的值,總共6個函數,和前面的6個函數完全類似:

    type __sync_add_and_fetch (type *ptr, type value, ...)

    type __sync_sub_and_fetch (type *ptr, type value, ...)

    type __sync_or_and_fetch (type *ptr, type value, ...)

    type __sync_and_and_fetch (type *ptr, type value, ...)

    type __sync_xor_and_fetch (type *ptr, type value, ...)

    type __sync_nand_and_fetch (type *ptr, type value, ...)

  2.3 把變量的值和某個值比較,如果相等就把變量的值設置為新的值,總共2個函數:

    bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)   

      返回是否相等,相當於

         if ( *ptr == oldval ) {*ptr = newval; return true;}

                          else {return false;}

    type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

      返回修改前的值,相當於

         tmp = *ptr 

         if ( *ptr == oldval ) { *ptr= newval; }

                          return tmp ;

  2.4 鎖定測試-設置 及 解鎖,總共2個函數: 

    type __sync_lock_test_and_set (type *ptr, type value, ...)

      把變量的值設置為新值,並返回設置前的值,相當於tmp = *ptr; return tmp

    void __sync_lock_release (type *ptr, ...)  

      把變量的值設置為0,相當於 *ptr = 0  通過查看匯編代碼,可以看出這個函數使用了內存屏障,然后再把變量的值置為0

            這兩個函數可以實現自旋鎖

3. 自旋鎖的實現:boost實現如下,在spinlock_sync.hpp 

class spinlock
{
public:
    int v_;
public:

    bool try_lock()
    {
        int r = __sync_lock_test_and_set( &v_, 1 );
        return r == 0;
    }

    void lock()
    {
        for( unsigned k = 0; !try_lock(); ++k )
        {
            //等待一些指令周期
            boost::detail::yield( k );
        }
    }

    void unlock()
    {
        __sync_lock_release( &v_ );
    }
};

 

悲觀鎖和樂觀鎖
獨占鎖是一種悲觀鎖,synchronized就是一種獨占鎖,它假設最壞的情況,並且只有在確保其它線程不會造成干擾的情況下執行,會導致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。而另一個更加有效的鎖就是樂觀鎖。所謂樂觀鎖就是,每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。

CAS操作
Compare and Swap,比較並操作,CPU指令,在大多數處理器架構,包括IA32、Space中采用的都是CAS指令,CAS的語義是“我認為V的值應該為A,如果是,那么將V的值更新為B,否則不修改並告訴V的值實際為多少”,CAS是項樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程並不會被掛起,而是被告知這次競爭中失敗,並可以再次嘗試。CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改為B,否則什么都不做。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM