日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

聊聊原子操作那些事

發(fā)布時(shí)間:2025/3/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 聊聊原子操作那些事 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??

原子操作,線程間交互數(shù)據(jù)最細(xì)粒度的同步操作,它可以保證線程間讀寫(xiě)某個(gè)數(shù)值的原子性。

由于不需要加重量級(jí)的互斥鎖進(jìn)行同步,因此非常輕量,而且也不需要在內(nèi)核間來(lái)回切換調(diào)度,效率是非常高的。。

那如何使用原子操作了,各個(gè)平臺(tái)下都有相關(guān)api提供了支持,并且向gcc、clang這些編譯器,也提供了編譯器級(jí)的__builtin接口進(jìn)行支持

  • windows的Interlockedxxx和Interlockedxxx64系列api
  • macosx的OSAtomicXXX系列api
  • gcc的__sync_val_compare_and_swap和__sync_val_compare_and_swap_8等__builtin接口
  • x86和x86_64架構(gòu)的lock匯編指令
  • tbox的跨平臺(tái)原子接口
  • tbox接口使用

    先拿tbox的tb_atomic_fetch_and_add接口為例,顧名思義,這個(gè)api會(huì)先讀取原有數(shù)值,然后在其基礎(chǔ)上加上一個(gè)數(shù)值:

    // 相當(dāng)于原子進(jìn)行:b = *a++; tb_atomic_t a = 0; tb_long_t b = tb_atomic_fetch_and_add(&a, 1);

    如果需要先進(jìn)行add計(jì)算,再返回結(jié)果可以用:

    // 相當(dāng)于原子進(jìn)行:b = ++*a; tb_atomic_t a = 0; tb_long_t b = tb_atomic_add_and_fetch(&a, 1);

    或者可以更加簡(jiǎn)化為:

    tb_long_t b = tb_atomic_fetch_and_inc(&a); tb_long_t b = tb_atomic_inc_and_fetch(&a);

    那tbox在內(nèi)部如何去適配各個(gè)平臺(tái)的呢,我們可以簡(jiǎn)單看下,基本上就是對(duì)原生api進(jìn)行了一層wrap而已。

    windows接口封裝

    static __tb_inline__ tb_long_t tb_atomic_fetch_and_add_windows(tb_atomic_t* a, tb_long_t v) {return (tb_long_t)InterlockedExchangeAdd((LONG __tb_volatile__*)a, v); } static __tb_inline__ tb_long_t tb_atomic_inc_and_fetch_windows(tb_atomic_t* a) {return (tb_long_t)InterlockedIncrement((LONG __tb_volatile__*)a); }

    gcc接口的封裝

    static __tb_inline__ tb_long_t tb_atomic_fetch_and_add_sync(tb_atomic_t* a, tb_long_t v) {return __sync_fetch_and_add(a, v); }

    x86和x86_64架構(gòu)匯編實(shí)現(xiàn)

    static __tb_inline__ tb_long_t tb_atomic_fetch_and_add_x86(tb_atomic_t* a, tb_long_t v) {/** xaddl v, [a]:** o = [a]* [a] += v;* v = o;** cf, ef, of, sf, zf, pf... maybe changed*/__tb_asm__ __tb_volatile__ ( #if TB_CPU_BITSIZE == 64"lock xaddq %0, %1 \n" //!< xaddq v, [a] #else"lock xaddl %0, %1 \n" //!< xaddl v, [a] #endif: "+r" (v) : "m" (*a) : "cc", "memory");return v; }

    原子操作除了可以進(jìn)行對(duì)int32和int64數(shù)值加減乘除外,還可以進(jìn)行xor, or, and等邏輯計(jì)算,用法類似,這里就不多說(shuō)了。

    下面我們?cè)賮?lái)個(gè)簡(jiǎn)單的實(shí)例,來(lái)實(shí)際運(yùn)用下,原子的應(yīng)用場(chǎng)景還是蠻多的,比如:

    • 用于實(shí)現(xiàn)自旋鎖
    • 用于實(shí)現(xiàn)無(wú)鎖隊(duì)列
    • 線程間的狀態(tài)同步
    • 用于實(shí)現(xiàn)單例

    等等。。

    自旋鎖的實(shí)現(xiàn)

    我們先來(lái)看下如何去實(shí)現(xiàn)一個(gè)簡(jiǎn)單的自旋鎖,為了統(tǒng)一規(guī)范演示代碼,下面的代碼都用tbox提供的原子接口為例:

    static __tb_inline_force__ tb_bool_t tb_spinlock_init(tb_spinlock_ref_t lock) {// init *lock = 0;// okreturn tb_true; } static __tb_inline_force__ tb_void_t tb_spinlock_exit(tb_spinlock_ref_t lock) {// exit *lock = 0; } static __tb_inline_force__ tb_void_t tb_spinlock_enter(tb_spinlock_ref_t lock) {/* 嘗試讀取lock的狀態(tài)值,如果還沒(méi)獲取到lock(狀態(tài)0),則獲取它(設(shè)置為1)* 如果對(duì)方線程已經(jīng)獲取到lock(狀態(tài)1),那么循環(huán)等待嘗試重新獲取** 注:整個(gè)狀態(tài)讀取和設(shè)置,是原子的,無(wú)法被打斷*/tb_size_t tryn = 5;while (tb_atomic_fetch_and_pset((tb_atomic_t*)lock, 0, 1)){// 沒(méi)獲取到lock,嘗試5次后,還不成功,則讓出cpu切到其他線程運(yùn)行,之后重新嘗試獲取if (!tryn--){// yieldtb_sched_yield();// reset tryntryn = 5;}} } static __tb_inline_force__ tb_void_t tb_spinlock_leave(tb_spinlock_ref_t lock) {// 釋放lock,此處無(wú)需原子,設(shè)置到一半被打斷,數(shù)值部位0,對(duì)方線程還是在等待中,不收影響*((tb_atomic_t*)lock) = 0; }

    這個(gè)實(shí)現(xiàn)非常簡(jiǎn)單,但是tbox里面,基本上默認(rèn)都是在使用這個(gè)spinlock,因?yàn)閠box里面大部分多線程實(shí)現(xiàn),粒度都被拆的很細(xì)

    大部分情況下,用自旋鎖就ok了,無(wú)需進(jìn)入內(nèi)核態(tài)切換等待。。

    使用方式如下:

    // 獲取lock tb_spinlock_enter(&lock);// 一些同步操作 // ..// 釋放lock tb_spinlock_leave(&lock);

    上面的代碼中,省略了init和exit操作,實(shí)際使用時(shí),在響應(yīng)初始化和釋放的地方,做相應(yīng)處理下就行了。。

    類pthread_once的實(shí)現(xiàn)

    pthread_once 可以在多線程函數(shù)內(nèi),可以保證傳入的函數(shù)只被調(diào)用到一次,一般可以用來(lái)初始化全局單例或者TLS的key初始化

    以tbox的接口為例,我先來(lái)來(lái)看下,這個(gè)函數(shù)的使用方式:

    // 初始化函數(shù),只會(huì)被調(diào)用到一次 static tb_void_t tb_once_func(tb_cpointer_t priv) {// 初始化一些單例對(duì)象,全局變量// 或者執(zhí)行一些初始化調(diào)用 }// 線程函數(shù) static tb_int_t tb_thread_func(tb_cpointer_t priv) {// 全局存儲(chǔ)lock,并初始化為0static tb_atomic_t lock = 0;if (tb_thread_once(&lock, tb_once_func, "user data")){// ok} }

    我們這里拿原子操作,可以簡(jiǎn)單模擬實(shí)現(xiàn)下這個(gè)函數(shù):

    tb_bool_t tb_thread_once(tb_atomic_t* lock, tb_bool_t (*func)(tb_cpointer_t), tb_cpointer_t priv) {// checktb_check_return_val(lock && func, tb_false);/* 原子獲取lock的狀態(tài)** 0: func還沒(méi)有被調(diào)用* 1: 已經(jīng)獲取到lock,func正在被其他線程調(diào)用中* 2: func已經(jīng)被調(diào)用完成,并且func返回ok* -2: func已經(jīng)被調(diào)用,并且func返回失敗failed*/tb_atomic_t called = tb_atomic_fetch_and_pset(lock, 0, 1);// func已經(jīng)被其他線程調(diào)用過(guò)了?直接返回if (called && called != 1) {return called == 2;}// func還沒(méi)有被調(diào)用過(guò)?那么調(diào)用它else if (!called){// 調(diào)用函數(shù)tb_bool_t ok = func(priv);// 設(shè)置返回狀態(tài)tb_atomic_set(lock, ok? 2 : -1);// ok?return ok;}// 正在被其他線程獲取到lock,func正在被調(diào)用中,還沒(méi)完成?嘗試等待lockelse{// 此處簡(jiǎn)單的做了些sleep循環(huán)等待,直到對(duì)方線程func執(zhí)行完成tb_size_t tryn = 50;while ((1 == tb_atomic_get(lock)) && tryn--){// wait some timetb_msleep(100);}}/* 重新獲取lock的狀態(tài),判斷是否成功* * 成功:2* 超時(shí):1* 失敗:-2** 此處只要不是2,都算失敗*/return tb_atomic_get(lock) == 2; }

    64位原子操作

    64位操作跟32位的接口使用方式,是完全一樣的,僅僅只是變量類型的區(qū)別:

  • tbox中類型為tb_atomic64_t,接口改為tb_atomic64_xxxx
  • gcc中類型為volatile long long,接口改為_(kāi)_sync_xxxx_8系列
  • windows上則為Interlockedxxx64
  • 具體使用方式參考32位,這里就不詳細(xì)介紹了。。


    個(gè)人主頁(yè):TBOOX開(kāi)源工程

    轉(zhuǎn)載于:https://my.oschina.net/tboox/blog/754016

    總結(jié)

    以上是生活随笔為你收集整理的聊聊原子操作那些事的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲色图影院 | 免费黄色网址在线 | 亚洲成人av | 尤物av在线| 香港黄色网 | 91美女片黄在线观看游戏 | 亚洲免费色视频 | 野花视频在线观看免费 | 国产一区二区免费视频 | 色欧美在线 | 色婷婷av一区二区 | 人人舔人人干 | 97超级碰碰人妻中文字幕 | 亚洲精品国产a | 中日韩中文字幕一区二区 | 日本a√在线观看 | 精品一区二区毛片 | 亚洲女人在线 | 欧美日韩一区二区中文字幕 | 国产aaa级片 | 日韩一级片免费看 | 国产精品天美传媒沈樵 | 日韩二区| 女同性αv亚洲女同志 | 天天干天天色综合 | 欧美另类老妇 | 成人午夜视频在线 | 黄色仓库av | 狠狠干香蕉 | 欧美乱插| 欧美成人精品网站 | 免费中文av | 水牛影视av一区二区免费 | 日韩欧美天堂 | 91精品视频免费 | 午夜寂寞视频 | 免费在线日本 | 欧美日韩一区二区在线观看 | 99精品视频免费版的特色功能 | 一区二区三区四区高清视频 | av成人在线电影 | 欧美成人免费高清视频 | 一级一片免费播放 | 欧美日韩亚洲视频 | 嫩草天堂| 一区二区在线视频免费观看 | 亚洲av成人无码久久精品老人 | 欧美久久精品一级黑人c片 1000部多毛熟女毛茸茸 | 精品人妻一区二区色欲产成人 | 超碰在线中文字幕 | 成人免费在线播放视频 | 久久久久久欧美 | 少妇激情一区二区三区视频 | 夜晚福利视频 | 在线少妇 | 国产91国语对白在线 | 精品视频在线一区 | 五月激情婷婷丁香 | 女生喷液视频 | 色噜噜日韩精品欧美一区二区 | 色屁屁一区二区三区视频 | 老妇free性videosxx | 九九热视频精品在线观看 | 日本激情视频在线 | 成人欧美一区二区三区黑人 | 最近中文字幕mv | www.亚洲视频 | 伊人伊人网 | 国产嫩草影视 | 91精品国产高清一区二区三密臀 | 亚洲精品国产精品国自产网站按摩 | 国产亚洲性欧美日韩在线观看软件 | 乱子伦一区二区三区 | 吻胸摸激情床激烈视频大胸 | 欧美人与禽zozzo性之恋的特点 | 欧美亚洲在线播放 | 国产精品麻豆成人av电影艾秋 | 99在线视频免费观看 | 国产成人在线免费视频 | 亚洲春色一区二区三区 | 91午夜精品| 久久黄色网址 | 欧美精品在线一区 | 黄色网址你懂的 | av免费网址在线观看 | 69视频入口| 国产精品夜夜 | 美女娇喘 | 在线视频成人 | 免费看黄禁片 | 亚洲小说春色综合另类 | 激情久久一区 | 极品久久久 | 丁香六月激情综合 | 国产精品腿扒开做爽爽爽挤奶网站 | 亚洲av无码乱码在线观看性色 | www.人人干 | 免费古装一级淫片潘金莲 | 国产成人精品无码免费看在线 |