最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言原子操作的實現(xiàn)示例

 更新時間:2025年12月18日 11:12:43   作者:山,離天三尺三  
本文主要介紹了C語言中原子操作,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

原子操作是并發(fā)編程中的一個核心概念。讓我詳細解釋:

什么是原子操作?

原子操作是指在執(zhí)行過程中不會被中斷的操作,要么完全執(zhí)行,要么完全不執(zhí)行,不會出現(xiàn)部分執(zhí)行的狀態(tài)。

比喻理解

就像原子是不可分割的基本單位一樣,原子操作是不可分割的操作單位。

非原子操作的問題

先看一個非原子操作的例子:

int counter = 0;

// 這不是原子操作!
void increment() {
    counter = counter + 1;
}

在匯編層面,這通常分為三步:

mov eax, [counter]  ; 1. 讀取counter到寄存器
inc eax             ; 2. 寄存器值加1
mov [counter], eax  ; 3. 寫回內(nèi)存

競態(tài)條件問題

線程A:讀取counter=0
線程B:讀取counter=0  
線程A:計算0+1=1
線程B:計算0+1=1
線程A:寫入counter=1
線程B:寫入counter=1  ← 結(jié)果應該是2,但實際是1!

C語言中的原子操作

C11標準引入的原子類型

#include <stdatomic.h>

// 聲明原子變量
atomic_int atomic_counter = ATOMIC_VAR_INIT(0);

// 原子操作
void increment_atomic() {
    atomic_fetch_add(&atomic_counter, 1);  // 原子加法
}

int main() {
    atomic_counter = 5;                    // 原子存儲
    int value = atomic_counter;            // 原子加載
    printf("Counter: %d\n", value);
    
    return 0;
}

常見的原子操作函數(shù)

基本操作

#include <stdatomic.h>

atomic_int counter = ATOMIC_VAR_INIT(0);

// 加載和存儲
int load_value = atomic_load(&counter);        // 原子讀取
atomic_store(&counter, 42);                    // 原子寫入

// 交換操作
int old_value = atomic_exchange(&counter, 100); // 原子交換

// 比較交換(CAS - Compare And Swap)
int expected = 100;
if (atomic_compare_exchange_strong(&counter, &expected, 200)) {
    printf("CAS成功: 舊值=%d, 新值=200\n", expected);
}

算術(shù)運算

// 原子加法
int old = atomic_fetch_add(&counter, 5);    // counter += 5,返回舊值

// 原子減法  
atomic_fetch_sub(&counter, 3);              // counter -= 3

// 原子自增/自減
atomic_fetch_add(&counter, 1);              // counter++
atomic_fetch_sub(&counter, 1);              // counter--

位運算

atomic_int flags = ATOMIC_VAR_INIT(0);

// 原子位操作
atomic_fetch_or(&flags, 0x01);     // flags |= 0x01
atomic_fetch_and(&flags, ~0x01);   // flags &= ~0x01
atomic_fetch_xor(&flags, 0x03);    // flags ^= 0x03

原子操作的實際例子

1. 無鎖計數(shù)器

#include <stdatomic.h>
#include <pthread.h>
#include <stdio.h>

atomic_int counter = ATOMIC_VAR_INIT(0);

void* worker(void* arg) {
    for (int i = 0; i < 100000; i++) {
        atomic_fetch_add(&counter, 1);  // 原子自增
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;
    
    pthread_create(&t1, NULL, worker, NULL);
    pthread_create(&t2, NULL, worker, NULL);
    
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    
    printf("最終計數(shù): %d (應該是200000)\n", atomic_load(&counter));
    return 0;
}

2. 自旋鎖實現(xiàn)

#include <stdatomic.h>

typedef atomic_flag spinlock_t;

void spinlock_init(spinlock_t* lock) {
    atomic_flag_clear(lock);
}

void spinlock_lock(spinlock_t* lock) {
    // 忙等待,直到獲得鎖
    while (atomic_flag_test_and_set(lock)) {
        // 可選的:減少CPU占用
        // __builtin_ia32_pause();  // x86的PAUSE指令
    }
}

void spinlock_unlock(spinlock_t* lock) {
    atomic_flag_clear(lock);
}

3. 無鎖棧(Lock-Free Stack)

#include <stdatomic.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node* next;
} Node;

typedef struct {
    _Atomic(Node*) top;
} LockFreeStack;

void stack_init(LockFreeStack* stack) {
    atomic_store(&stack->top, NULL);
}

void stack_push(LockFreeStack* stack, int value) {
    Node* new_node = malloc(sizeof(Node));
    new_node->data = value;
    
    Node* old_top;
    do {
        old_top = atomic_load(&stack->top);
        new_node->next = old_top;
    } while (!atomic_compare_exchange_weak(&stack->top, &old_top, new_node));
}

int stack_pop(LockFreeStack* stack) {
    Node* old_top;
    Node* new_top;
    
    do {
        old_top = atomic_load(&stack->top);
        if (old_top == NULL) return -1;  // ???
        new_top = old_top->next;
    } while (!atomic_compare_exchange_weak(&stack->top, &old_top, new_top));
    
    int value = old_top->data;
    free(old_top);
    return value;
}

內(nèi)存順序(Memory Order)

原子操作還涉及內(nèi)存可見性問題:

#include <stdatomic.h>

atomic_int data = ATOMIC_VAR_INIT(0);
atomic_int flag = ATOMIC_VAR_INIT(0);

// 生產(chǎn)者線程
void producer() {
    atomic_store_explicit(&data, 42, memory_order_relaxed);
    atomic_store_explicit(&flag, 1, memory_order_release);  // 釋放語義
}

// 消費者線程
void consumer() {
    while (atomic_load_explicit(&flag, memory_order_acquire) == 0) {
        // 等待
    }
    int value = atomic_load_explicit(&data, memory_order_relaxed);
    printf("Data: %d\n", value);  // 保證看到42
}

不同平臺的原生原子操作

x86架構(gòu)

// 內(nèi)聯(lián)匯編實現(xiàn)原子操作
int atomic_increment(int* value) {
    __asm__ __volatile__(
        "lock incl %0"          // lock前綴確保原子性
        : "+m" (*value)
        :
        : "cc"
    );
    return *value;
}

GCC內(nèi)置原子操作

int counter = 0;

// GCC內(nèi)置的原子操作
void increment_gcc() {
    __sync_fetch_and_add(&counter, 1);
}

int compare_and_swap_gcc(int* ptr, int oldval, int newval) {
    return __sync_val_compare_and_swap(ptr, oldval, newval);
}

原子操作的優(yōu)缺點

優(yōu)點:

  • 高性能:避免鎖的開銷
  • 無死鎖:不會出現(xiàn)鎖順序問題
  • 可擴展性:在多核系統(tǒng)中表現(xiàn)良好

缺點:

  • 復雜性:正確實現(xiàn)很困難
  • ABA問題:在CAS操作中可能出現(xiàn)
  • 平臺依賴性:不同硬件支持程度不同

原子操作 vs 互斥鎖

特性原子操作互斥鎖
性能高(硬件支持)中等(系統(tǒng)調(diào)用)
復雜度
適用場景簡單操作(計數(shù)器、標志位)復雜臨界區(qū)
死鎖風險
可擴展性一般

總結(jié)

原子操作是:

  • 不可分割的操作單位
  • 線程安全的,無需額外同步
  • 硬件支持的,通常通過CPU指令實現(xiàn)
  • 高性能的并發(fā)編程基礎(chǔ)

在現(xiàn)代多核處理器系統(tǒng)中,原子操作是實現(xiàn)高效并發(fā)程序的重要工具,特別是在實現(xiàn)無鎖數(shù)據(jù)結(jié)構(gòu)、計數(shù)器、標志位等場景中。

到此這篇關(guān)于C語言原子操作的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)C語言 原子操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解如何將c語言文件打包成exe可執(zhí)行程序

    詳解如何將c語言文件打包成exe可執(zhí)行程序

    這篇文章主要介紹了詳解如何將c語言文件打包成exe可執(zhí)行程序,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • C++求階乘的兩種方法

    C++求階乘的兩種方法

    這篇文章主要介紹了C++求階乘的兩種方法,有需要的朋友可以參考一下
    2013-12-12
  • 淺談C++虛重載操作符 virtual operator= 的使用方法

    淺談C++虛重載操作符 virtual operator= 的使用方法

    下面小編就為大家?guī)硪黄獪\談C++虛重載操作符 virtual operator= 的使用方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • Linux UDP服務端和客戶端程序的實現(xiàn)

    Linux UDP服務端和客戶端程序的實現(xiàn)

    這篇文章主要介紹了Linux UDP服務端和客戶端程序的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-05-05
  • 關(guān)于單片機按鍵問題性能提升總結(jié)

    關(guān)于單片機按鍵問題性能提升總結(jié)

    今天小編就為大家分享一篇關(guān)于關(guān)于單片機按鍵問題性能提升總結(jié),小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • C++讀取帶空格字符串的方法

    C++讀取帶空格字符串的方法

    今天小編就為大家分享一篇C++讀取帶空格字符串的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • 從入門到精通C++11?<chrono>?庫特性

    從入門到精通C++11?<chrono>?庫特性

    chrono庫是C++11中一個非常強大和實用的庫,它為時間處理提供了豐富的功能和類型安全的接口,通過本文的介紹,我們了解了chrono庫的基本概念,感興趣的朋友一起看看吧
    2025-06-06
  • 使用devenv在命令行中編譯項目的方法

    使用devenv在命令行中編譯項目的方法

    下面小編就為大家分享一篇使用devenv在命令行中編譯項目的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • c++中的string常用函數(shù)用法總結(jié)

    c++中的string常用函數(shù)用法總結(jié)

    以下是對c++中的string常用函數(shù)的用法進行了詳細的分析介紹,需要的朋友可以過來參考下
    2013-09-09
  • C++中的運算符和運算符優(yōu)先級總結(jié)

    C++中的運算符和運算符優(yōu)先級總結(jié)

    這篇文章主要介紹了C++中的運算符和運算符優(yōu)先級總結(jié),主要整理了算術(shù)、關(guān)系、邏輯、位和賦值運算符的用法,需要的朋友可以參考下
    2016-05-05

最新評論

东台市| 鹰潭市| 太康县| 渝北区| 新蔡县| 耿马| 隆林| 潢川县| 玉田县| 沁水县| 葫芦岛市| 大足县| 夹江县| 晴隆县| 古蔺县| 城口县| 龙江县| 潞西市| 自贡市| 神农架林区| 韩城市| 喜德县| 南丹县| 扶绥县| 铜山县| 云南省| 建瓯市| 遵化市| 海阳市| 工布江达县| 贺兰县| 南郑县| 富锦市| 凤凰县| 体育| 许昌市| 阳新县| 彭阳县| 绍兴市| 海兴县| 开封市|