2012-08-22 Linux下原子操作
阿新 • • 發佈:2019-02-03
今天在開發的過程中遇到這麼一個情形,有兩個執行緒分別對一個 map 中的同一變數進行寫操作(其中一個是加1操作,另一個是賦零操作),這樣會很不安全,通常情況下大家肯定會首先考慮用互斥鎖,但是使用執行緒互斥鎖之後效能會下降很多,那麼我就選擇了原子操作,而原子操作的效能比互斥鎖高很多,這裡有一篇文章講到它們之間的效能比較:http://imcc.blogbus.com/logs/179131763.html。
於是上網找了關於原子操作的資料,所謂原子操作,就是該操作絕不會在執行完畢前被任何其他任務或事件打斷,也就說,它的最小的執行單位,不可能有比它更小的執行單位,因此這裡的原子實際是使用了物理學裡的物質微粒的概念。 然而大部分資料都說原子操作是定義在 include/asm/atomic.h
檔案中,但是我在 ubuntu 下搜尋這個標頭檔案,根本搜尋不到,後來才知道如果沒有 atomic.h 標頭檔案的時候,我們也可以使用原子操作,gcc從4.1.2提供了__sync_*系列的built-in函式,用於提供加減和邏輯運算的原子操作。
type __sync_fetch_and_add (type *ptr, type value, ...)
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, 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, ...)
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...) 這兩個函式提供原子的比較和交換,如果*ptr == oldval,就將newval寫入*ptr,
第一個函式在相等並寫入的情況下返回true.
第二個函式在返回操作之前的值。 還有兩個函式:
type __sync_lock_test_and_set (type *ptr, type value, ...)
將*ptr設為value並返回*ptr操作之前的值。
void __sync_lock_release (type *ptr, ...)
將*ptr置0
於是我們可以用巨集來把這些原子操作的函式封裝一下:
// The atomic of increment one
#define atomic_inc(x) __sync_add_and_fetch((x),1)
// The atomic of set to zero
#define atomic_set_zero(x) __sync_lock_release(x)
// The atomic of set
#define atomic_set(x, y) __sync_lock_test_and_set((x), (y)) 博主所有文章已轉自私人部落格Joe 的個人部落格,謝謝關注!
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...) 這兩個函式提供原子的比較和交換,如果*ptr == oldval,就將newval寫入*ptr,
第一個函式在相等並寫入的情況下返回true.
第二個函式在返回操作之前的值。 還有兩個函式:
type __sync_lock_test_and_set (type *ptr, type value, ...)
將*ptr設為value並返回*ptr操作之前的值。
void __sync_lock_release (type *ptr, ...)
將*ptr置0
於是我們可以用巨集來把這些原子操作的函式封裝一下:
// The atomic of increment one
#define atomic_inc(x) __sync_add_and_fetch((x),1)
// The atomic of set to zero
#define atomic_set_zero(x) __sync_lock_release(x)
// The atomic of set
#define atomic_set(x, y) __sync_lock_test_and_set((x), (y)) 博主所有文章已轉自私人部落格Joe 的個人部落格,謝謝關注!