成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

CPU瘋狂打轉(zhuǎn)背后的故事:一篇文章教你理解自旋鎖!

開發(fā) 前端
自旋鎖其實(shí)就是一種“死磕到底”的鎖,適用于那種“等一下就能用”的情況。現(xiàn)實(shí)生活中也有很多類似的場(chǎng)景,比如公共健身器材的排隊(duì),等電梯,等等。理解了“自旋”其實(shí)就是一種“忙等”方式,才能更好地應(yīng)對(duì)面試中的各種多線程問(wèn)題。

前言

想象一下,你去上班,發(fā)現(xiàn)電梯壞了。站在電梯口等著,心里想著“它馬上就會(huì)好吧?”。于是,你開始重復(fù)按著電梯按鈕,一分鐘又一分鐘地等著,心里甚至有點(diǎn)煩躁。這種狀態(tài)就像“自旋”一樣——你站在原地,做著重復(fù)的動(dòng)作,不走開,等著電梯修好。

在計(jì)算機(jī)世界里,“自旋”指的就是這種不斷重復(fù)、原地等待的狀態(tài)。今天,我們就來(lái)聊聊“自旋鎖”是什么,為啥要用它,它又是怎么工作的。

一、自旋是什么?

在多線程編程中,如果多個(gè)線程要訪問(wèn)同一個(gè)資源,就必須協(xié)調(diào)好,不能一起上去“搶”。為了避免數(shù)據(jù)混亂,我們常用鎖機(jī)制來(lái)管理這些資源,而“自旋鎖”就是其中一種特殊的鎖。

那么,什么是“自旋”呢?

自旋的本質(zhì),就是一個(gè)“等”的動(dòng)作。某個(gè)線程在等待資源解鎖時(shí),不去睡眠、不去做別的任務(wù),而是持續(xù)檢查——“資源解鎖了嗎?解鎖了嗎?”。這種重復(fù)檢查、原地等待的動(dòng)作,就是“自旋”。當(dāng)資源解鎖時(shí),它可以立刻進(jìn)入使用,而不用浪費(fèi)時(shí)間重新“醒過(guò)來(lái)”。

二、形象化理解:小區(qū)公共健身器材

想象你住的小區(qū),有一套公共健身器材,比如單杠。周末你想去玩單杠,但到了發(fā)現(xiàn)前面有人在用。你很想盡快上去,但也不想離開,萬(wàn)一人家馬上玩完了呢?于是,你站在一旁,隨時(shí)準(zhǔn)備上場(chǎng)。

這時(shí),有兩種選擇:

  • 選項(xiàng)A: 站在旁邊等,眼睛緊盯著單杠,直到前面那人下來(lái),立馬沖上去!這就是“自旋鎖”的方式。
  • 選項(xiàng)B: 先去跑個(gè)圈、做點(diǎn)別的,等回來(lái)再看前面的人走沒走,這種叫“休眠鎖”,類似于互斥鎖。

在選項(xiàng)A中,你會(huì)一直“自旋”等待著機(jī)會(huì),但這種方式只有在“前面那個(gè)人快要結(jié)束”的情況下才有意義,否則一直站著等,既浪費(fèi)時(shí)間又累。所以,自旋鎖適用于等待時(shí)間短、資源即將釋放的場(chǎng)景。

三、 自旋鎖和互斥鎖的區(qū)別是什么?

自旋鎖和互斥鎖(Mutex)都能保證同一時(shí)間只有一個(gè)線程能訪問(wèn)共享資源,但它們的區(qū)別在于:

  • 互斥鎖:如果線程沒有拿到鎖,它會(huì)進(jìn)入休眠狀態(tài),等鎖釋放后再喚醒,可能會(huì)產(chǎn)生一些“調(diào)度開銷”。
  • 自旋鎖:如果線程沒有拿到鎖,它不會(huì)休眠,而是“原地自旋”等待鎖的釋放,減少了調(diào)度的開銷。

因此,自旋鎖 特別適合那種“等待時(shí)間很短”的情況,比如一段代碼塊執(zhí)行非常快,線程只需稍微等一下就能拿到鎖,這時(shí)自旋鎖就能顯著減少開銷。

四、先了解自旋鎖的基本接口

在 Linux 的pthread庫(kù)中,我們可以用pthread_spin_init來(lái)初始化一個(gè)自旋鎖,用pthread_spin_lock和pthread_spin_unlock來(lái)上鎖和解鎖。

注意,自旋鎖與互斥鎖不同,自旋鎖不允許等待的線程進(jìn)入“休眠”,而是不斷檢查鎖是否可用。

pthread_spinlock_t spin;
pthread_spin_init(&spin, 0);  // 初始化自旋鎖

pthread_spin_lock(&spin);     // 自旋等待獲取鎖
// 訪問(wèn)共享資源
pthread_spin_unlock(&spin);   // 釋放鎖

pthread_spin_destroy(&spin);  // 銷毀自旋鎖

五、實(shí)際代碼示例

在 Linux 內(nèi)核或多線程編程中,自旋鎖是一種重要的同步機(jī)制。以下是一個(gè)簡(jiǎn)單的自旋鎖代碼示例,用于模擬多線程的共享資源訪問(wèn):

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

int shared_data = 0;
pthread_spinlock_t spinlock;

void* increment_data(void* arg) {
    pthread_spin_lock(&spinlock);  // 加鎖,開始“自旋”
    shared_data++;
    printf("Thread %d: shared_data = %d\n", *(int*)arg, shared_data);
    pthread_spin_unlock(&spinlock);  // 解鎖,停止“自旋”
    return NULL;
}

int main() {
    pthread_t threads[5];
    pthread_spin_init(&spinlock, 0);  // 初始化自旋鎖

    int thread_ids[5] = {0, 1, 2, 3, 4};
    for (int i = 0; i < 5; i++) {
        pthread_create(&threads[i], NULL, increment_data, &thread_ids[i]);
    }

    for (int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }

    pthread_spin_destroy(&spinlock);  // 銷毀自旋鎖
    return 0;
}

在上面的代碼中,每個(gè)線程都嘗試去訪問(wèn)shared_data這個(gè)共享變量。通過(guò)自旋鎖機(jī)制,線程會(huì)一直“等”到其他線程釋放鎖,確保每次只有一個(gè)線程可以修改shared_data,避免了數(shù)據(jù)混亂。

六、 自旋鎖的應(yīng)用場(chǎng)景:什么時(shí)候用自旋鎖?

自旋鎖的特點(diǎn),就是“急”,不愿意浪費(fèi)時(shí)間等待。它適合那些等待時(shí)間短、需要快速響應(yīng)的情況,常見的場(chǎng)景有這些:

  1. 小任務(wù):比如你只是要讀取或修改一個(gè)小變量,操作很快完成,沒必要讓線程進(jìn)入休眠再醒來(lái),這種情況下自旋鎖很合適。它能讓線程馬上完成任務(wù),釋放鎖,保持流程流暢。
  2. 多核系統(tǒng):在多核系統(tǒng)里,自旋鎖更有優(yōu)勢(shì),因?yàn)橐粋€(gè)核在“忙等”時(shí),其他核還能正常工作。這樣線程不被阻塞,能有效提高整個(gè)系統(tǒng)的運(yùn)行效率。
  3. 操作系統(tǒng)內(nèi)核的關(guān)鍵任務(wù):在操作系統(tǒng)內(nèi)核中,很多任務(wù)要求速度快、等待時(shí)間短,自旋鎖的特性就很適用。自旋鎖能確保關(guān)鍵資源在被短時(shí)間鎖定時(shí),不產(chǎn)生過(guò)多的調(diào)度開銷。

總之,自旋鎖 適合那些“等一小會(huì)兒就能用到”的情況,如果任務(wù)很簡(jiǎn)單、耗時(shí)很短,用它就能提高效率。但如果任務(wù)復(fù)雜、需要長(zhǎng)時(shí)間鎖定資源,還是換成別的鎖更靠譜(比如互斥鎖)。

七、自旋鎖的陷阱:CPU高占用

自旋鎖的主要風(fēng)險(xiǎn)是會(huì)導(dǎo)致 CPU 高占用。假設(shè)一個(gè)線程長(zhǎng)時(shí)間持有鎖,其他線程就會(huì)一直自旋等待,浪費(fèi) CPU。

解決方法:設(shè)置最大等待次數(shù)

可以給自旋鎖設(shè)置一個(gè)“最多等幾次”的限制。比如,如果等了5次還沒拿到鎖,那就放棄,不再繼續(xù)浪費(fèi)CPU。這種方式在 Linux 的 pthread_spin_trylock 實(shí)現(xiàn)中經(jīng)常被使用。

簡(jiǎn)單代碼示例

以下是一個(gè)帶限制的自旋鎖示例:

int try_spinlock_with_limit(pthread_spinlock_t *lock, int max_attempts) {
    int attempt = 0;
    while (attempt < max_attempts) {
        if (pthread_spin_trylock(lock) == 0) {  // 成功拿到鎖
            return 0;
        }
        attempt++;
    }
    return -1;  // 達(dá)到最大次數(shù),放棄
}

這里每次加鎖最多等 5 次,沒拿到鎖就直接放棄。這樣可以避免CPU一直空耗在等待上,提升效率。

八、自旋鎖的優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  1. 快速響應(yīng):自旋鎖不涉及上下文切換的開銷,在資源會(huì)快速釋放的情況下,自旋等待更節(jié)省時(shí)間。
  2. 適合多核處理:在多核系統(tǒng)中,一個(gè)核的線程“自旋”等待時(shí),另一個(gè)核的線程可以繼續(xù)工作,實(shí)現(xiàn)更好的并行性。

缺點(diǎn)

  1. CPU占用高:自旋鎖的線程不會(huì)釋放CPU資源,所以等待時(shí)間長(zhǎng)時(shí)會(huì)浪費(fèi)CPU。
  2. 只能短期等待:如果鎖被長(zhǎng)期占用,自旋鎖會(huì)導(dǎo)致資源浪費(fèi),還不如直接睡眠。這個(gè)時(shí)候使用互斥鎖可能會(huì)更好。

九、C++ 如何實(shí)現(xiàn)自旋鎖?

在 C/C++ 編程中, 只有 Linuxpthread 庫(kù)提供了自旋鎖相關(guān)接口,而在 C++ 標(biāo)準(zhǔn)庫(kù)中,并沒有直接提供自旋鎖(spinlock)的接口。不過(guò),你可以使用 std::atomic_flag 來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的自旋鎖,因?yàn)?std::atomic_flag 是一個(gè)輕量級(jí)的原子布爾標(biāo)志,非常適合構(gòu)建自旋鎖。

下面是一個(gè)使用 std::atomic_flag 實(shí)現(xiàn)自旋鎖的示例:

#include <atomic>
#include <thread>

class SpinLock {
private:
    std::atomic_flag flag = ATOMIC_FLAG_INIT;

public:
    void lock() {
        while (flag.test_and_set(std::memory_order_acquire)) {
            // 自旋等待,直到獲得鎖
        }
    }

    void unlock() {
        flag.clear(std::memory_order_release);
    }
};

使用方法:

SpinLock spinlock;

void critical_section() {
    spinlock.lock();
    // 臨界區(qū)代碼
    spinlock.unlock();
}

說(shuō)明:

  • 自旋鎖的實(shí)現(xiàn):lock() 方法中使用了 test_and_set,它會(huì)不斷嘗試將 flag 設(shè)置為 true,直到成功獲取鎖。如果鎖已經(jīng)被其他線程占用,它會(huì)進(jìn)入自旋等待狀態(tài),持續(xù)嘗試獲取鎖。
  • 釋放鎖:unlock() 方法通過(guò) clear 將 flag 設(shè)為 false,釋放鎖,使其他線程可以進(jìn)入臨界區(qū)。

十、總結(jié)

自旋鎖其實(shí)就是一種“死磕到底”的鎖,適用于那種“等一下就能用”的情況。現(xiàn)實(shí)生活中也有很多類似的場(chǎng)景,比如公共健身器材的排隊(duì),等電梯,等等。理解了“自旋”其實(shí)就是一種“忙等”方式,才能更好地應(yīng)對(duì)面試中的各種多線程問(wèn)題。

希望這篇文章讓你對(duì)“自旋鎖”有了更全面、清晰的理解。下次面試時(shí),再遇到這個(gè)面試題,你一定能從容應(yīng)答,既講清原理,又能結(jié)合實(shí)際應(yīng)用,輕松拿下!

責(zé)任編輯:武曉燕 來(lái)源: 跟著小康學(xué)編程
相關(guān)推薦

2017-09-05 08:52:37

Git程序員命令

2022-10-08 15:07:06

ChatOps運(yùn)維

2019-07-15 07:58:10

前端開發(fā)技術(shù)

2021-07-13 11:37:47

cpu架構(gòu)Linux

2020-03-31 08:37:31

遞歸單鏈表反轉(zhuǎn)

2021-03-08 09:15:46

日志Filebeat運(yùn)維

2024-05-17 10:05:06

Java機(jī)制應(yīng)用

2020-10-09 08:15:11

JsBridge

2021-04-07 13:28:21

函數(shù)程序員異步

2020-12-29 05:35:43

FlinkSQL排序

2022-02-21 09:44:45

Git開源分布式

2023-05-12 08:19:12

Netty程序框架

2019-04-17 15:16:00

Sparkshuffle算法

2021-04-09 08:40:51

網(wǎng)絡(luò)保險(xiǎn)網(wǎng)絡(luò)安全網(wǎng)絡(luò)風(fēng)險(xiǎn)

2024-06-25 08:18:55

2021-06-30 00:20:12

Hangfire.NET平臺(tái)

2018-05-31 09:44:01

微服務(wù)架構(gòu)數(shù)據(jù)

2023-09-06 14:57:46

JavaScript編程語(yǔ)言

2020-12-08 08:09:49

SVG圖標(biāo)Web

2019-09-24 14:19:12

PythonC語(yǔ)言文章
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩精品一区二区三区视频播放 | 国产精品成人一区二区三区夜夜夜 | 免费成人在线网站 | 亚洲欧美一区二区三区在线 | 日韩一二三| 日韩久久综合网 | 福利片一区二区 | 亚洲va中文字幕 | 成人深夜福利网站 | 国产高清在线观看 | 亚洲欧美在线视频 | 新91视频网 | 欧美精品tv | 黄视频国产| 成人免费视频 | 乳色吐息在线观看 | av电影一区| 97超级碰碰| 毛片av免费看 | 欧美日韩精品久久久免费观看 | 中文字幕久久久 | 婷婷久久综合 | 久久精品青青大伊人av | 久久综合爱 | 日本欧美黄色片 | 精品伊人 | 有码在线 | 亚洲影音先锋 | 成人毛片一区二区三区 | 亚洲综合色视频在线观看 | av在线一区二区三区 | 欧美久久久久久久久 | 黄色大片在线 | 天天草夜夜骑 | 亚洲欧美一区二区三区情侣bbw | 91麻豆精品国产91久久久更新资源速度超快 | 国产福利在线播放 | 亚洲黄色片免费观看 | 99精品欧美一区二区三区 | 成人欧美一区二区 | 久久最新精品视频 |