原子操作是不可分割的操作,在執行完畢時它不會被任何事件中斷,原子操作是多數無鎖程式設計的基本前提。
atomic是原子的意思,意味"不可分割"的整體。在linux kernel中有一類atomic操作api。這些操作對使用者而言是原子執行的,在乙個cpu上執行過程中,不會被其他cpu打斷。最常見的操作是原子讀改寫,簡稱rmw。
原子操作需要硬體的支援,檢視核心原始碼中的atomic_*函式,最終都是採用彙編執行,通過鎖記憶體匯流排、記憶體屏障等方式來實現的。下一章會以cas方法(例x86指令cmpxchgl)來舉例說明。
原子操作主要用於實現資源計數,很多引用計數就是通過原子操作實現的。原子型別定義如下:
typedef struct atomic_t;
volatile修飾字段告訴gcc不要對該型別的資料做優化處理。
對它的訪問都是對記憶體的訪問,而不是對暫存器的訪問。
原子操作api包括:
atomic_read(atomic_t * v);
該函式對原子型別的變數進行原子讀操作,它返回原子型別的變數v的值。
atomic_set(atomic_t * v, int i);
該函式設定原子型別的變數v的值為i。
void atomic_add(int i, atomic_t *v);
該函式給原子型別的變數v增加值i。
atomic_sub(int i, atomic_t *v);
該函式從原子型別的變數v中減去i。
int atomic_sub_and_test(int i, atomic_t *v);
該函式從原子型別的變數v中減去i,並判斷結果是否為0,如果為0,返回真,否則返回假。
void atomic_inc(atomic_t *v);
該函式對原子型別變數v原子地增加1。
void atomic_dec(atomic_t *v);
該函式對原子型別的變數v原子地減1。
int atomic_dec_and_test(atomic_t *v);
該函式對原子型別的變數v原子地減1,並判斷結果是否為0,如果為0,返回真,否則返回假。
int atomic_inc_and_test(atomic_t *v);
該函式對原子型別的變數v原子地增加1,並判斷結果是否為0,如果為0,返回真,否則返回假。
int atomic_add_negative(int i, atomic_t *v);
該函式對原子型別的變數v原子地增加i,並判斷結果是否為負數,如果是,返回真,否則返回假。
int atomic_add_return(int i, atomic_t *v);
該函式對原子型別的變數v原子地增加i,並且返回指向v的指標。
int atomic_sub_return(int i, atomic_t *v);
該函式從原子型別的變數v中減去i,並且返回指向v的指標。
int atomic_inc_return(atomic_t * v);
該函式對原子型別的變數v原子地增加1並且返回指向v的指標。
int atomic_dec_return(atomic_t * v);
該函式對原子型別的變數v原子地減1並且返回指向v的指標。
gcc內建的__sync_*函式提供了加減和邏輯運算的原子操作,一共有十二個函式
type __sync_fetch_and_add (type *ptr, typevalue)
;type __sync_fetch_and_sub (type *ptr, type value)
;type __sync_fetch_and_or (type *ptr, type value)
;type __sync_fetch_and_and (type *ptr, type value)
;type __sync_fetch_and_xor (type *ptr, type value)
;type __sync_fetch_and_nand (type *ptr, type value)
;type __sync_add_and_fetch (type *ptr, typevalue)
;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)
;
type可以是1,2,4或8位元組長度的int型別,即:
int8_t / uint8_t
int16_t / uint16_t
int32_t / uint32_t
int64_t / uint64_t
(1)匯流排鎖bus lock:使用處理器提供乙個lock#訊號,當乙個處理器在匯流排上輸出此訊號的時候,其他處理器的請求將被阻塞,那麼該處理器可以獨佔使用共享記憶體。匯流排鎖是把cpu和記憶體之間通訊鎖住了,這使得鎖定期間,其他處理器不能操作其他記憶體位址的資料,所以匯流排鎖鎖定的開銷比較大。
(2)快取鎖定cacheline lock:基本都採用快取一致性協議(mesi)。
這部分可以參考:
《現代作業系統:原書第4版》:第8章:多處理機系統
說說無鎖(lock-free)程式設計那些事:
《現代作業系統:原書第4版》
《多核程式設計入門》
atomic實現原理:
cache之多核一致性(一) - 匯流排上沒有秘密:
原子操作以及加鎖機制:
說說無鎖(lock-free)程式設計那些事:
GPU程式設計和流式多處理器(七)
將第二個運算 加,最小或最大值 應用於中間結果和第三個運算數。通過引用內建變數threadidx,blockidx,blockdim和griddim,訪問許多特殊暫存器。這些偽變數將在3節中詳細介紹,它們是3維結構,分別指定執行緒id,塊id,執行緒數和塊數。除此之外,另乙個特殊暫存器,sm的時鐘暫...
多處理器程式設計的藝術 pdf格式
多處理器程式設計的藝術 從原理和實踐兩個方面全面闡述了多處理器程式設計的指導原則,包含編制高效的多處理器程式所必備的演算法技術。此外,附錄提供了採用其他程式語言包 如c c及c 的pthreads庫 進行程式設計的相關背景知識以及硬體基礎知識。多處理器程式設計的藝術 適合作為高等院校計算機及相關專業...
作業系統(3) 多處理器程式設計 從入門到放棄
入門 理解多執行緒 三個放棄 原子性 有序性 可見性 程序與執行緒的區別 執行緒的建立 include include include void mythread void arg intmain int argc,char ar 執行結果 可以看到,執行緒建立後,可能立即執行,也可能處於就緒狀態,...