iOS底層-鎖的原理

鎖在我們開發(fā)中用的相對(duì)比較少漏麦,但是作為一個(gè)開發(fā)者,還是需要了解鎖的原理;

下圖是鎖的性能數(shù)據(jù)圖:

iShot2020-11-14 11.42.00.png

鎖的歸類

  • 自旋鎖:線程反復(fù)檢查鎖變量是否可用昧捷。由于線程在這一過程中保持執(zhí)行, 因此是一種忙等待罐寨。一旦獲取了自旋鎖靡挥,線程會(huì)一直保持該鎖,直至顯式釋 放自旋鎖鸯绿。 自旋鎖避免了進(jìn)程上下文的調(diào)度開銷跋破,因此對(duì)于線程只會(huì)阻塞很 短時(shí)間的場(chǎng)合是有效的。
  • 互斥鎖:是一種用于多線程編程中瓶蝴,防止兩條線程同時(shí)對(duì)同一公共資源(比 如全局變量)進(jìn)行讀寫的機(jī)制毒返。該目的通過將代碼切片成一個(gè)一個(gè)的臨界區(qū) 而達(dá)成
  • 條件鎖:就是條件變量,當(dāng)進(jìn)程的某些資源要求不滿足時(shí)就進(jìn)入休眠舷手,也就是鎖住了饿悬。當(dāng)資源被分配到了,條件鎖打開聚霜,進(jìn)程繼續(xù)運(yùn)行
  • 遞歸鎖:就是同一個(gè)線程可以加鎖N次而不會(huì)引發(fā)死鎖
  • 信號(hào)量:是一種更高級(jí)的同步機(jī)制狡恬,互斥鎖可以說是semaphore在僅取值0/1時(shí)的特例。信號(hào)量可以有更多的取值空間蝎宇,用來實(shí)現(xiàn)更加復(fù)雜的同步弟劲,而不單單是線程間互斥
  • 讀寫鎖:讀寫鎖實(shí)際是一種特殊的自旋鎖,它把對(duì)共享資源的訪問者劃分成讀者和寫者姥芥,讀者只對(duì)共享資源 進(jìn)行讀訪問兔乞,寫者則需要對(duì)共享資源進(jìn)行寫操作,這種鎖相對(duì)于自旋鎖而言凉唐,能提高并發(fā)性庸追,它允許同時(shí)有多個(gè)讀者來訪問共享資源。

其實(shí)基本的鎖就包括了三類 自旋鎖 互斥鎖 讀寫鎖台囱,
其他的比如條件鎖淡溯,遞歸鎖,信號(hào)量都是上層的封裝和實(shí)現(xiàn)!

  • 互斥鎖在上圖包括:NSLock簿训,pthread_mutex咱娶,@synchronized
  • 條件鎖有:NSCondition米间,NSConditionLock
  • 遞歸鎖:NSRecursiveLock,pthread_mutex(recursive)
  • 信號(hào)量:dispatch_semaphore

互斥鎖與遞歸鎖

在開發(fā)中膘侮,我們常用的大概是@synchronized屈糊,就從這個(gè)開始講解;
下面使用@synchronized來舉一個(gè)例子:
鎖的應(yīng)用是為了線程的安全執(zhí)行琼了,例如購(gòu)票逻锐,不同線程購(gòu)票不加鎖的話,會(huì)出現(xiàn)同一張票被賣多次雕薪。
下面看一段代碼:

- (void)saleTicket{
    @synchronized (self) {
        if (self.ticketCount > 0) {
            self.ticketCount--;
            sleep(0.1);
            NSLog(@"當(dāng)前余票還剩:%ld張",self.ticketCount)
        }else{
            NSLog(@"當(dāng)前車票已售罄");
        }
    }
}

通過@synchronized對(duì)票數(shù)的減少進(jìn)行加鎖之后谦去,我們執(zhí)行程序后,就不會(huì)出現(xiàn)問題蹦哼。
下圖是執(zhí)行后的打印結(jié)果:

iShot2020-11-14 17.37.40.png

那既然@synchronized能夠保證線程的安全鳄哭,那就先去看一下它的底層原理;

首先創(chuàng)建一個(gè)iOS工程纲熏,在main.m函數(shù)中加上@synchronized (appDelegateClassName) { }這句代碼妆丘,對(duì)main函數(shù)進(jìn)行xcrun -sdk iphonesimulator clang -arch x86_64 -rewrite-objc main.m轉(zhuǎn)換成cpp文件。

接下來就看一下main函數(shù)中的@synchronized轉(zhuǎn)化之后變成的代碼塊:

  {
            id _rethrow = 0;
            id _sync_obj = (id)appDelegateClassName;
            objc_sync_enter(_sync_obj);

            try {
                struct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {} ~_SYNC_EXIT() {objc_sync_exit(sync_exit);}
                    id sync_exit;
                } 
                _sync_exit(_sync_obj);

            } catch (id e) {_
            rethrow = e;
            }
            
            {
                struct _FIN {
                _FIN(id reth) : rethrow(reth) {}
    ~_FIN() { if (rethrow) objc_exception_throw(rethrow); }
    id rethrow;
    }
                _fin_force_rethow(_rethrow);}
}

可以看到它有一個(gè)objc_sync_enter_sync_exit局劲;
通過對(duì)objc_sync_enter的斷點(diǎn)查看勺拣,得知@synchronized的底層在libobjc.A.dylib中。

下圖是objc_sync_enter的源碼實(shí)現(xiàn)鱼填,可以看到它傳入了obj之后药有,就會(huì)進(jìn)行處理,而沒有傳入時(shí)苹丸,就會(huì)調(diào)用objc_sync_nil()函數(shù)愤惰,這個(gè)函數(shù)沒有任何實(shí)現(xiàn)。

iShot2020-11-14 18.06.23.png

也就是說赘理,當(dāng)@synchronized(nil)括號(hào)中傳入的是nil宦言,它什么都不做,無法起作用商模。
在有值的情況下奠旺,會(huì)對(duì)mutex進(jìn)行lock()加鎖函數(shù)的調(diào)用,那么看一下objc_sync_exit的函數(shù)實(shí)現(xiàn):

iShot2020-11-14 18.13.09.png

可以看到在objc_sync_exit中會(huì)對(duì)mutex調(diào)用tryUnlock()解鎖函數(shù)。

那么重點(diǎn)就是SyncData了施流,它是一個(gè)結(jié)構(gòu)體:

iShot2020-11-14 18.19.45.png

而結(jié)構(gòu)體中最重要的就是recursive_mutex_t

iShot2020-11-14 18.22.11.png

它是一個(gè)recursive_mutex_tt類响疚,在這個(gè)類中有lockunlock兩個(gè)方法,是一個(gè)遞歸鎖瞪醋。

那么回到objc_sync_enter忿晕,鎖的創(chuàng)建是由id2data創(chuàng)建的,這個(gè)函數(shù)代碼很多趟章,下圖是一部分代碼杏糙,主要功能是通過kvc的方式拿到data值;

iShot2020-11-14 18.34.24.png

if(data)判斷中蚓土,有對(duì)ACQUIRERELEASE的方法實(shí)現(xiàn):

iShot2020-11-14 18.35.19.png

其中lockCount表示被鎖了多少次宏侍,可重入,比遞歸鎖功能更強(qiáng)大蜀漆,因?yàn)樵诓榭?code>SyncData時(shí)谅河,它是一個(gè)鏈表結(jié)構(gòu)。
上面的代碼是在SUPPORT_DIRECT_THREAD_KEYS的情況下的确丢,而不在這個(gè)情況下绷耍,也跟上面的代碼差不多;
SUPPORT_DIRECT_THREAD_KEYS是從線程棧緩存的形式鲜侥,而endif是從cache的形式獲取去緩存褂始。

而如果第一次加載時(shí),就會(huì)從下面的代碼執(zhí)行:


iShot2020-11-14 18.48.14.png
iShot2020-11-14 18.49.42.png

也就是說描函,第一次進(jìn)來崎苗,會(huì)通過kvc對(duì)tls進(jìn)行設(shè)值和標(biāo)記,設(shè)置threadCount = 1舀寓,lockCount = 1胆数,在線程棧存空間和緩存空間中都會(huì)進(jìn)行處理。

那么一個(gè)完整的流程也就很清晰了互墓。

總結(jié):@synchronized整個(gè)流程其實(shí)就是一張哈希表必尼,因?yàn)榈讓臃庋b的是recursive_mutex_t,所以是一把遞歸鎖,擴(kuò)展了遞歸鎖里面增加了lockCount篡撵,防止多線程的重入判莉,增加了threadCount進(jìn)行處理。

@synchronized這把鎖的性能是比較低的育谬,因?yàn)槔锩嬗泻芏噫湵淼牟樵兟钭猓彺妫聦哟a的查找斑司,導(dǎo)致了性能是比較差渗饮;但是為什么用的多呢,因?yàn)榉奖愫?jiǎn)單宿刮,好用互站。

下面來看一段代碼:

for (int i = 0; i < 200; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            _testArray = [NSMutableArray array];
        });
    }

這一段代碼是使用異步函數(shù)創(chuàng)建數(shù)組對(duì)象,這一段代碼是有問題的僵缺,因?yàn)椴粩嗟某跏蓟瘜?dǎo)致了問題胡桃,沒銷毀就創(chuàng)建,多個(gè)線程創(chuàng)建同一個(gè)對(duì)象磕潮,釋放一次還好翠胰,釋放多次容贝,僵尸對(duì)象,就造成野指針之景。

那么防止問題的產(chǎn)生可以進(jìn)行加鎖斤富;例如使用@synchronized(),那么括號(hào)內(nèi)的參數(shù)可以填什么呢?
如果是填_testArray锻狗,那么還是會(huì)存在問題满力,因?yàn)榇嬖谀骋粋€(gè)臨界點(diǎn),_testArray會(huì)變成nil轻纪,那么鎖nil就會(huì)出問題油额;可以進(jìn)行鎖self,因?yàn)?code>self是持有者刻帚,它是有一個(gè)生命周期的潦嘶。

那么除了用@synchronized,在性能和對(duì)objc的生命周期不明確時(shí)崇众,還可以使用NSLock衬以;
在創(chuàng)建數(shù)組前執(zhí)行[lock lock],在創(chuàng)建之后執(zhí)行[lock unlock];

下面來研究一下NSRecursiveLockNSLock這兩把鎖的使用,看下面一段代碼:

NSRecursiveLock *recursiveLock = [[NSRecursiveLock alloc] init];
 NSLock *lock = [[NSLock alloc] init];
for (int i= 0; i<100; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            static void (^testMethod)(int);
            testMethod = ^(int value){
                if (value > 0) {
                  NSLog(@"current value = %d",value);
                  testMethod(value - 1);
                }
            };
            testMethod(10);
        });
    }

這段代碼進(jìn)行了函數(shù)的嵌套調(diào)用校摩,會(huì)產(chǎn)生遞歸看峻,那么如何加鎖使其不產(chǎn)生遞歸呢?

通常一般情況下衙吩,我們會(huì)在方法執(zhí)行前加鎖和方法執(zhí)行結(jié)束進(jìn)行解鎖互妓,也就是說在testMethod函數(shù)前調(diào)用[lock lock]testMethod(10)之后執(zhí)行[lock unlock];那這樣做產(chǎn)生的后果就是它會(huì)循環(huán)10次從10到1的結(jié)果坤塞,這是一種解決方法冯勉;

那如果在testMethod方法里的if判斷外加鎖在if判斷外解鎖,這樣會(huì)產(chǎn)生循環(huán)遞歸問題摹芙,因?yàn)?code>Lock是一把簡(jiǎn)單的互斥鎖灼狰,當(dāng)執(zhí)行testMethod進(jìn)行加鎖,之后又調(diào)用testMethod浮禾,又一次加鎖交胚,也就是不同的線程進(jìn)行加鎖,當(dāng)想要解鎖時(shí)盈电,因?yàn)槠渌€程已經(jīng)加鎖了蝴簇,需要等待其他線程進(jìn)行解鎖。

那么NSLock是無法解決這種遞歸的特性匆帚,使用@synchronized也是可以的熬词,但是效果也是執(zhí)行10次從10到1。

那么使用NSRecursiveLock這把遞歸鎖,是可以很好的解決這個(gè)問題的互拾。

testMethod方法前調(diào)用[recursiveLock lock];if判斷結(jié)束后調(diào)用[recursiveLock unlock];是可以解決問題的歪今。

NSRecursiveLockLock的底層都是在pthread的基礎(chǔ)上進(jìn)行封裝的;而他們的代碼實(shí)現(xiàn)大部分是一樣的颜矿,但是NSRecursiveLock的初始化的地方與NSLock是有區(qū)別的寄猩,看下面兩張圖片:

底層源碼是來自swift的Foundation框架。


NSLock.png
NSRecursiveLock.png

那么關(guān)于NSLockNSRecursiveLock的使用就介紹完了或衡,總的來說焦影,使用是比較麻煩的车遂,在使用便捷方面封断,@synchronized更簡(jiǎn)單、實(shí)用舶担,而這兩把鎖就比較復(fù)雜坡疼,但是性能會(huì)比較高一些。

條件鎖

下面來研究一下NSCondition這把鎖衣陶;

1:[condition lock];//一般用于多線程同時(shí)訪問柄瑰、修改同一個(gè)數(shù)據(jù)源,保證在同一 時(shí)間內(nèi)數(shù)據(jù)源只被訪問剪况、修改一次教沾,其他線程的命令需要在lock 外等待,只到 unlock 译断,才可訪問
2:[condition unlock];//與lock 同時(shí)使用
3:[condition wait];//讓當(dāng)前線程處于等待狀態(tài)
4:[condition signal];//CPU發(fā)信號(hào)告訴線程不用在等待授翻,可以繼續(xù)執(zhí)行

NSCondition的對(duì)象實(shí)際上作為一個(gè)鎖和一個(gè)線程檢查器:鎖主要 為了當(dāng)檢測(cè)條件時(shí)保護(hù)數(shù)據(jù)源,執(zhí)行條件引發(fā)的任務(wù);線程檢查器 主要是根據(jù)條件決定是否繼續(xù)運(yùn)行線程孙咪,即線程是否被阻塞堪唐。

它適用于一個(gè)生產(chǎn)消費(fèi)者模型;
看代碼:

- (void)testConditon{
    
    _testCondition = [[NSCondition alloc] init];
    //創(chuàng)建生產(chǎn)-消費(fèi)者
    for (int i = 0; i < 50; i++) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            [self producer];
        });
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            [self consumer];
        });
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            [self consumer];
        });
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            [self producer];
        });
    }
}

- (void)producer{
    [_testCondition lock]; // 操作的多線程影響
    self.ticketCount = self.ticketCount + 1;
    NSLog(@"生產(chǎn)一個(gè) 現(xiàn)有 count %zd",self.ticketCount);
    [_testCondition signal]; // 信號(hào)
    [_testCondition unlock];
}

- (void)consumer{
 
     [_testCondition lock];  // 操作的多線程影響
    if (self.ticketCount == 0) {
        NSLog(@"等待 count %zd",self.ticketCount);
        [_testCondition wait];
    }
    //注意消費(fèi)行為翎蹈,要在等待條件判斷之后
    self.ticketCount -= 1;
    NSLog(@"消費(fèi)一個(gè) 還剩 count %zd ",self.ticketCount);
     [_testCondition unlock];
}

上面的代碼執(zhí)行流程需要先生產(chǎn)出來淮菠,才能消費(fèi),當(dāng)消費(fèi)多了荤堪,還沒生產(chǎn)完合陵,就需要等待。
那么為了避免多線程的影響澄阳,需要對(duì)生產(chǎn)的時(shí)候進(jìn)行加鎖曙寡,防止它還為生產(chǎn)完,就進(jìn)行消費(fèi)了寇荧,當(dāng)生產(chǎn)完了举庶,發(fā)送一個(gè)信號(hào),再進(jìn)行解鎖揩抡。

那么新增需求户侥,當(dāng)我們需要對(duì)事務(wù)進(jìn)行順序處理時(shí)镀琉,如何使用鎖來處理;那就要介紹一下NSConditionLock這把條件鎖了蕊唐,
看代碼:

// 信號(hào)量
    NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:2];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
         [conditionLock lockWhenCondition:1]; // conditoion = 1 內(nèi)部 Condition 匹配
        // -[NSConditionLock lockWhenCondition: beforeDate:]
        NSLog(@"線程 1");
         [conditionLock unlockWithCondition:0];
    });
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
       
        [conditionLock lockWhenCondition:2];
        sleep(0.1);
        NSLog(@"線程 2");
        // self.myLock.value = 1;
        [conditionLock unlockWithCondition:1]; // _value = 2 -> 1
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
       [conditionLock lock];
       NSLog(@"線程 3");
       [conditionLock unlock];
    });

這把鎖的特殊性在于這把鎖是有一個(gè)條件屋摔,通過設(shè)置信號(hào)量lockWhenCondition,在執(zhí)行時(shí)會(huì)對(duì)信號(hào)量進(jìn)行匹配替梨,首先執(zhí)行線程3钓试,因?yàn)樗鼪]有設(shè)置信號(hào)量,然后信號(hào)量進(jìn)行匹配副瀑,由于初始化時(shí)設(shè)置了信號(hào)量為2弓熏,因此先執(zhí)行線程2,在里面又設(shè)置了解鎖信號(hào)量為1糠睡,就匹配線程1挽鞠,如果解鎖信號(hào)量與線程1的信號(hào)量不匹配,那么線程1不會(huì)執(zhí)行狈孔。

注意信认,線程3與線程2的順序有可能是不確定的,如果線程3比較耗時(shí)均抽,那么有可能會(huì)先執(zhí)行線程2嫁赏,再執(zhí)行線程1,最后執(zhí)行線程3.

那么關(guān)于其他的一些鎖這邊就不再介紹了油挥。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末潦蝇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子喘漏,更是在濱河造成了極大的恐慌护蝶,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翩迈,死亡現(xiàn)場(chǎng)離奇詭異持灰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)负饲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門堤魁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人返十,你說我怎么就攤上這事妥泉。” “怎么了洞坑?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵盲链,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)刽沾,這世上最難降的妖魔是什么本慕? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮侧漓,結(jié)果婚禮上锅尘,老公的妹妹穿的比我還像新娘。我一直安慰自己布蔗,他們只是感情好藤违,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纵揍,像睡著了一般顿乒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上骡男,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天淆游,我揣著相機(jī)與錄音傍睹,去河邊找鬼隔盛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拾稳,可吹牛的內(nèi)容都是我干的吮炕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼访得,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼龙亲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悍抑,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤鳄炉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后搜骡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拂盯,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年记靡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谈竿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摸吠,死狀恐怖空凸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寸痢,我是刑警寧澤呀洲,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響道逗,放射性物質(zhì)發(fā)生泄漏丛楚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一憔辫、第九天 我趴在偏房一處隱蔽的房頂上張望趣些。 院中可真熱鬧,春花似錦贰您、人聲如沸坏平。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舶替。三九已至,卻和暖如春杠园,著一層夾襖步出監(jiān)牢的瞬間顾瞪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工抛蚁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陈醒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓瞧甩,卻偏偏與公主長(zhǎng)得像钉跷,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肚逸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 鎖的種類 借用網(wǎng)上的一張有關(guān)鎖性能的對(duì)比圖爷辙,如下所示: 從上圖中我們可以看出來,鎖大概可以分為以下幾種: 1.:在...
    含笑州閱讀 1,005評(píng)論 0 0
  • iOS 底層原理 文章匯總[http://www.reibang.com/p/412b20d9a0f6] 本文主...
    Style_月月閱讀 4,371評(píng)論 9 16
  • 目錄:1.為什么要線程安全2.多線程安全隱患分析3.多線程安全隱患的解決方案4.鎖的分類-13種鎖4.1.1OSS...
    二斤寂寞閱讀 1,183評(píng)論 0 3
  • 了解鎖的機(jī)制會(huì)有助于項(xiàng)目開發(fā)朦促,從而避免項(xiàng)目中多個(gè)線程訪問同一塊資源引發(fā)數(shù)據(jù)混亂的問題膝晾。 一 概念 鎖的歸類 基本...
    yan0_0閱讀 291評(píng)論 0 2
  • 轉(zhuǎn)鏈接:https://juejin.im/post/5d395318f265da1b8608ca98 自旋鎖 O...
    DL是誰閱讀 481評(píng)論 0 0