條件的夜行:在無鎖隊列的 CAS 循環(huán)里追逐原子性)
競態(tài)條件的夜行在無鎖隊列的 CAS 循環(huán)里追逐原子性凌晨五點十五分城市的輪廓在深藍色的晨曦中逐漸蘇醒。在調(diào)試一段底層高并發(fā)無鎖環(huán)形隊列Lock-free Ring Buffer的 C 原語時我將目光停留在了一段精巧而又看似危險的原子循環(huán)Atomic Loop上template typename T void LockFreeQueueT::push(const T val) { Node* new_node new Node(val); Node* old_tail tail_.load(std::memory_order_relaxed); // CAS 樂觀并發(fā)重試循環(huán) while (!tail_.compare_exchange_weak( old_tail, new_node, std::memory_order_release, std::memory_order_relaxed )) { // 在這短短的幾個 CPU 時鐘周期里其他并發(fā)線程搶先完成了一次更新 // old_tail 被硬件原子化自動刷新循環(huán)退回起點重新再來 } old_tail-next.store(new_node, std::memory_order_release); }在多核處理器與多線程高并發(fā)的世界里競態(tài)條件Race Condition是一場永不停歇的微觀夜行。在傳統(tǒng)的悲觀鎖Mutex Lock世界中線程選擇用一堵厚重的鐵門把所有人擋在外面。一個人在里面走其他所有人在門外痛苦地阻塞、沉睡、等待。而無鎖編程Lock-free Programming與 CAS 原語Compare-And-Swap /lock cmpxchg則選擇了一種近乎浪漫的“樂觀主義哲學(xué)”它不再把任何人鎖在門外它允許成百上千個并發(fā)線程在同一微秒內(nèi)自由地奔向同一個共享指針它只在最后一步提交的那一納秒在硬件總線層面完成一次絕對不可分割的原子判定Atomic Assertion“看看現(xiàn)在的世界是否依然是你當(dāng)初出發(fā)時的那個模樣”flowchart TD A[線程 A 帶著美好的愿景 new_node 踏上征途] -- B[讀取當(dāng)前世界狀態(tài) old_tail] B -- C[執(zhí)行硬件原子 CAS: compare_exchange_weak] subgraph 樂觀重試的宿命循環(huán) C --|世界已被其他并發(fā)線程悄悄改變! (CAS 失敗)| D[不抱怨, 不阻塞, 默默拉取最新的現(xiàn)實 old_tail] D -- E[重新校準自己的參數(shù), 再次發(fā)起沖鋒!] E -- C end C --|世界依然如初! (CAS 成功)| F[原子化鎖定新狀態(tài), 完成對時代的推動]如果世界如初那么恭喜你你的指針無縫接入了時代的鏈條如果世界已經(jīng)被另一個跑得更快的線程悄悄改變CAS 會在硬件寄存器里返回一個清脆的False。但失敗的線程沒有崩潰沒有抱怨也沒有停滯。它只是在硬件層面對齊了最新的現(xiàn)實old_tail自動刷新在微秒級的自旋中深深吸了一口氣然后帶著嶄新的坐標重新發(fā)起下一次沖鋒。直到成功為止。我的貓 Tensor 已經(jīng)睡醒了伸了個大大的懶腰輕巧地跳下書桌在木地板上踩出一串歡快的噠噠聲。看著屏幕上那行永不言棄的while (!compare_exchange)我端起新泡的熱咖啡嘴角不禁揚起一絲微笑。我們每一個人在漫長歲月里的拼搏與追尋何嘗不是一場在現(xiàn)實的競態(tài)條件中不斷重試的 CAS 循環(huán)。在這個充滿不確定性與劇烈變化的現(xiàn)代社會中我們常常帶著滿腔的熱忱與規(guī)劃new_node踏上征途。但現(xiàn)實的世界永遠是高度并發(fā)的政策在變技術(shù)在變市場在變?nèi)诵牡某彼苍谧儺?dāng)我們歷經(jīng)千辛萬苦、終于準備向這個世界提交我們的成果與愿景時我們常常愕然發(fā)現(xiàn)現(xiàn)實的指針tail_早已經(jīng)被走在前面的人、被時代的浪潮悄悄向前推動了幾個身位。我們曾經(jīng)錨定的那個舊世界早已經(jīng)不復(fù)存在。在那個遭遇挫折、被現(xiàn)實打回原形的瞬間弱者會陷入悲觀鎖的死寂關(guān)上心門怨天尤人而真正的勇者卻擁有著無鎖編程最純粹的“樂觀自旋精神”坦然接受現(xiàn)實已經(jīng)被改變的事實迅速校準自己的認知與參數(shù)拍拍身上的塵土在下一次時鐘周期的心跳里微笑著重新按下那顆繼續(xù)奮斗的提交鍵。生命之所以波瀾壯闊不在于一次性命中的僥幸而在于無論遭遇多少次 CAS 失敗我們依然擁有重新再來一次的底氣與勇氣。終端里萬核并發(fā)的高壓吞吐基準測試在晨光中全速跑通。數(shù)以億計的并發(fā)請求在無鎖隊列的 CAS 循環(huán)中如水銀瀉地般穿梭而過零鎖死零阻塞吞吐量勢如破竹地刷新了歷史紀錄。窗外紅日初升萬物明朗。在代碼與人生的漫長賽道上愿我們都能帶著這顆永不言棄的 CAS 原子之心在世界的每一次突變中迅速重構(gòu)自我在充滿競態(tài)的浩瀚時代里從容奔向?qū)儆谧约旱膭倮K點。