?
このドキュメントでは、 php中國(guó)語(yǔ)ネットマニュアル リリース
_Atomic ( type-name ) | (1) | (since C11) |
---|---|---|
_Atomic type-name | (2) | (since C11) |
1)用作類(lèi)型說(shuō)明符; 這指定了一種新的原子類(lèi)型
2)用作類(lèi)型限定詞; 這指定了類(lèi)型名稱(chēng)的原子版本。在這個(gè)角色中,它可能與 const,volatile 和 restrict混合使用),但與其他限定符不同,type-name 的原子版本可能具有不同的大小,對(duì)齊和對(duì)象表示。
type-name | - | any type other than array or function. For (1), type-name also cannot be atomic or cvr-qualified |
---|
頭<stdatomic.h>
定義37層便于使用的宏,從atomic_bool
到atomic_uintmax_t
,這簡(jiǎn)化使用這個(gè)關(guān)鍵字與內(nèi)置和庫(kù)類(lèi)型的。
_Atomic const int * p1; // p is a pointer to an atomic const intconst atomic_int * p2; // sameconst _Atomic(int) * p3; // same
原子類(lèi)型的對(duì)象是唯一沒(méi)有數(shù)據(jù)競(jìng)爭(zhēng)的對(duì)象,也就是說(shuō),它們可以被兩個(gè)線程同時(shí)修改或修改一個(gè)并被另一個(gè)線程修改。
每個(gè)原子對(duì)象都有自己的關(guān)聯(lián)修改順序,這是對(duì)該對(duì)象進(jìn)行修改的總順序。如果從某個(gè)線程的角度來(lái)看,A
某些原子M的修改發(fā)生在修改B
相同的原子 M 之前,那么按M的修改順序,A 在 B 之前發(fā)生。
請(qǐng)注意,雖然每個(gè)原子對(duì)象都有自己的修改順序,但它不是總順序; 不同的線程可以觀察對(duì)不同順序的不同原子對(duì)象的修改。
所有原子操作都有四種連貫性保證:
寫(xiě) - 寫(xiě)連貫性:如果修改原子對(duì)象M的操作A 發(fā)生在修改M的操作B 之前,則A按修改順序M出現(xiàn)在B之前。
讀讀連貫性:如果原子對(duì)象M的值計(jì)算A在M的值計(jì)算B之前發(fā)生,并且A從M上的副作用X取其值,并且由B計(jì)算的值是由X存儲(chǔ)的值或者是由M上的副作用Y存儲(chǔ)的值,其中Y以M的修改順序比X晚出現(xiàn)。
讀寫(xiě)連貫性:如果原子對(duì)象M的值計(jì)算A在M上的操作B 之前發(fā)生,則A從M上的副作用X取其值,其中X以B的修改順序出現(xiàn)在M之前。
寫(xiě)讀連貫性:如果原子對(duì)象M上的副作用X 發(fā)生在 M 的值計(jì)算B 之前,則評(píng)估B從X或從修飾順序?yàn)镸的X之后出現(xiàn)的副作用Y中獲取其值。
一些原子操作也是同步操作; 他們可能會(huì)有額外的釋放語(yǔ)義,獲取語(yǔ)義或順序一致的語(yǔ)義???code>memory_order。
內(nèi)置增量和減量運(yùn)算符和復(fù)合賦值是按順序一致的順序進(jìn)行讀 - 修改 - 寫(xiě)原子操作(就像使用一樣memory_order_seq_cst
)。如果需要較不嚴(yán)格的同步語(yǔ)義,則可以使用標(biāo)準(zhǔn)庫(kù)函數(shù)。
原子屬性只對(duì)左值表達(dá)式有意義。左值到右值轉(zhuǎn)換(將從原子位置讀到CPU寄存器的內(nèi)存建模)與其他限定符一起剝離原子性。
如果宏常量__STDC_NO_ATOMICS__
(C11)由編譯器定義,則不提供關(guān)鍵字_Atomic
和標(biāo)題<stdatomic.h>
。
訪問(wèn)原子結(jié)構(gòu)/聯(lián)合的成員是未定義的行為。
庫(kù)類(lèi)型sig_atomic_t
不提供線程間同步或內(nèi)存排序,只有原子性。
易失性類(lèi)型不提供線程間同步,內(nèi)存排序或原子性。
_Atomic
.
#include <stdio.h>#include <threads.h>#include <stdatomic.h> atomic_int acnt;int cnt; int f(void* thr_data){ for(int n = 0; n < 1000; ++n) { ++cnt; ++acnt; // for this example, relaxed memory order is sufficient, e.g. // atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed); } return 0;} int main(void){ thrd_t thr[10]; for(int n = 0; n < 10; ++n) thrd_create(&thr[n], f, NULL); for(int n = 0; n < 10; ++n) thrd_join(thr[n], NULL); printf("The atomic counter is %u\n", acnt); printf("The non-atomic counter is %u\n", cnt);}
可能的輸出:
The atomic counter is 10000The non-atomic counter is 8644