gcc 原子操作 與 volatile

環境

Linux : 3.15.10-200.fc20.x86_64

gcc 版本 4.8.3 20140624 (Red Hat 4.8.3-1)


__sync_* 系列的函數 : 保證原子操作(lock 指令),也保證cpu寄存器數據一致性。(其實就是直接讀寫內存)

volatile : 保持寄存器數據一致性(每次重新讀寫內存到寄存器)


C代碼:

int main(void)
{
    volatile int a = 10;
    ++a;
    __sync_add_and_fetch(&a , 1);
    a = 100;
    a += 200;
    a -= 100;

    int b = 10;
    ++b;
    b = 100;
    b += 200;
    b -= 100;

    __sync_add_and_fetch(&a , b);
    a += b;

    return 0;
} 



關鍵看這兩行代碼對應的彙編指令:

    __sync_add_and_fetch(&a , b);                
    a += b; 

彙編指令:

main:                                                                                                                                                                   
.LFB0:         
        .cfi_startproc                                                                                                                                                  
        pushq   %rbp                                                                                                                                                    
        .cfi_def_cfa_offset 16                                                                                                                                          
        .cfi_offset 6, -16                                                                                                                                              
        movq    %rsp, %rbp                                                                                                                                              
        .cfi_def_cfa_register 6                                                                                                                                         
        movl    $10, -8(%rbp)                                                                                                                                           
        movl    -8(%rbp), %eax                                                                                                                                          
        addl    $1, %eax                                                                                                                                                
        movl    %eax, -8(%rbp)                                                                                                                                          
        lock addl       $1, -8(%rbp)                                                                                                                                    
        movl    $100, -8(%rbp)                                                                                                                                          
        movl    -8(%rbp), %eax                                                                                                                                          
        addl    $200, %eax                                                                                                                                              
        movl    %eax, -8(%rbp)                                                                                                                                          
        movl    -8(%rbp), %eax                                                                                                                                          
        subl    $100, %eax                                                                                                                                              
        movl    %eax, -8(%rbp)                                                                                                                                          
        movl    $10, -4(%rbp)                                                                                                                                           
        addl    $1, -4(%rbp)                                                                                                                                            
        movl    $100, -4(%rbp)                                                                                                                                          
        addl    $200, -4(%rbp)                                                                                                                                          
        subl    $100, -4(%rbp)                                                                                                                                          
        movl    -4(%rbp), %eax                                                                                                                                          
        lock addl       %eax, -8(%rbp)                                                                                                                                  
        movl    -8(%rbp), %edx                                                                                                                                          
        movl    -4(%rbp), %eax                                                                                                                                          
        addl    %edx, %eax                                                                                                                                              
        movl    %eax, -8(%rbp)                                                                                                                                          
        movl    $0, %eax                                                                                                                                                
        popq    %rbp                                                                                                                                                    
        .cfi_def_cfa 7, 8                                                                                                                                               
        ret                                                                                                                                                             
        .cfi_endproc



總結:

1:在併發編程中,如果你有一個多個線程訪問的變量。如果你要保證它的有效性且不想加volatile修飾符的話,那麼就要做到每次修改或訪問都是使用gcc的原子操作。

2:

2.1 CAS(cpu 硬件同步原語(compare and swap)): http://baike.baidu.com/subview/18179/6777667.htm

        2.2  volatile只是每次刷新值爲內存的值,沒有原子保證。

        2.3 原子操作,其實就是保證這一步的過程是原子的。但是,沒有保證值不會變(ABA問題)。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章