iOS常用的幾種鎖

前言

開發(fā)中引入了異步和多線程的來提高程序性能泡嘴,也就意味著線程安全成為了多線程的一個(gè)障礙甫恩,因此線程鎖應(yīng)運(yùn)而生,而鎖如果用不好酌予,還會(huì)造成死鎖的風(fēng)險(xiǎn)

下面就介紹ios中常用的幾種鎖磺箕,以及讀寫鎖的實(shí)現(xiàn)

案例demo

常見的多線程鎖

ios中常見的幾種鎖包括OSSpinLock、信號(hào)量(Semaphore)抛虫、pthread_mutex滞磺、NSLock、NSCondition莱褒、NSConditionLock击困、pthread_mutex(recursive)、NSRecursiveLock广凸、synchronized

如下所示阅茶,為前輩們測(cè)試鎖性能的案例圖(實(shí)際可能會(huì)略有偏差):

由于OSSpinLock目前已經(jīng)不再安全,這里就放棄介紹谅海,案例也把他給刪了??

我們?cè)龠x鎖的時(shí)候脸哀,如果只是使用互斥鎖的效果,那么按照性能排序選擇靠前的即可扭吁,如果需要鎖的一些其他功能撞蜂,那么根據(jù)需要選擇盲镶,不必過于局限于性能,畢竟實(shí)現(xiàn)功能與項(xiàng)目的維護(hù)也是非常重要的

其他鎖的使用如下所示

信號(hào)量(semaphore)

信號(hào)量實(shí)現(xiàn)加鎖功能與其他的略有不同蝌诡,其通過一個(gè)信號(hào)值來決定是否阻塞當(dāng)前線程

wait操作可以使得信號(hào)量值減少1溉贿,signal使得信號(hào)量值增加1

當(dāng)wait操作使得信號(hào)量值小于0時(shí),則所在線程阻塞阻塞休眠浦旱,使用signal使得信號(hào)量增加時(shí)宇色,會(huì)順序喚醒阻塞線程,以此便可以實(shí)現(xiàn)加鎖功能,

- (void)semaphore {
    _semaphore = dispatch_semaphore_create(1);
}

//wait操作可以使得信號(hào)量值減少1颁湖,signal使得信號(hào)量值增加1
//當(dāng)信號(hào)量值小于0時(shí)宣蠕,則所在線程阻塞休眠,使用signal使得信號(hào)量增加時(shí)甥捺,會(huì)順序喚醒阻塞線程
- (void)semaphoreUpdate {
    //wait 可以理解為加鎖操作抢蚀,信號(hào)值小于0會(huì)休眠當(dāng)前wait所在線程
    //第二個(gè)參數(shù) forever 為永遠(yuǎn),可以自行設(shè)置一段超時(shí)時(shí)間镰禾,達(dá)到等待時(shí)間會(huì)自動(dòng)解鎖
    dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);

    wait和singnal中間的這部分代碼,即為線程安全代碼
    _money++;

    //signal 可以解鎖
    dispatch_semaphore_signal(_semaphore);
}

pthread互斥鎖

pthread互斥鎖是 pthread 庫中的一員皿曲,linux系統(tǒng)中中常用的庫,使用時(shí)需要手動(dòng)import導(dǎo)入 #import <pthread/pthread.h>

其中有 pthread_mutex_trylock為嘗試加鎖,如果沒被加鎖羡微,則會(huì)加鎖成功谷饿,并返回0,適用于一些優(yōu)先級(jí)比較低妈倔,間歇性調(diào)用的功能

注意:其他部分鎖也有trylock這個(gè)功能博投,例如 NSLock、NSRecursiveLock盯蝴、NSConditionLock

#pragma mark --pthread互斥鎖
- (void)pthreadMutex {
    pthread_mutex_init(&_pMutexLock, NULL);
    //使用完畢后在合適的地方銷毀毅哗,例如dealloc
//    pthread_mutex_destroy(&_pMutexLock);
}

- (void)pthreadMutexUpdate {
    //加鎖代碼區(qū)間操作,避免多線程同時(shí)訪問
    pthread_mutex_lock(&_pMutexLock);
    _money++;
    //解鎖代碼區(qū)間操作
    pthread_mutex_unlock(&_pMutexLock);
}

- (void)pthreadMutexSub {
    //減少數(shù)值
    [NSThread detachNewThreadWithBlock:^{
        //數(shù)量大于100開始減少捧挺,假設(shè)是需要清理東西虑绵,這里減少數(shù)值
        while (self->_money > 10000) {
            //嘗試加鎖,如果能加鎖闽烙,則加鎖翅睛,返回零,否則返回不為零的數(shù)字
            //加鎖失敗休眠在執(zhí)行黑竞,避免搶奪資源捕发,此任務(wù)優(yōu)先級(jí)間接降低
            //其他的一些鎖也有這功能,例如NSLock、NSRecursiveLock很魂、NSConditionLock
            if (pthread_mutex_trylock(&self->_pMutexLock) == 0) {
                self->_money--;
                //解鎖
                pthread_mutex_unlock(&self->_pMutexLock);
            }else {
                [NSThread sleepForTimeInterval:1];
            }
        }
    }];
}

NSLock互斥鎖

NSLock 遵循 NSLocking協(xié)議,是常見的互斥鎖之一扎酷,為 OC 框架中的 API,使用方便遏匆,據(jù)說是 pthread 封裝的鎖

tryLock 方法也是嘗試加鎖法挨,成功返回true谁榜,失敗返回false

lockBeforeDate:(NSDate *)limit 在一個(gè)時(shí)間之間加鎖,可以理解為加鎖日期截止到指定時(shí)間凡纳,會(huì)自動(dòng)解鎖(與信號(hào)量的等待功能一樣窃植,這個(gè)是設(shè)置到指定時(shí)間)

#pragma mark --NSLock互斥鎖
- (void)NSLock {
    _lock = [[NSLock alloc] init];
}

- (void)NSLockUpdate {
    //加鎖代碼區(qū)間,避免多線程同時(shí)訪問
    [_lock lock];
    _money++;
    //解鎖代碼區(qū)間
    [_lock unlock];
}

NSCondition鎖

NSCondition 算是一個(gè)稍微重量級(jí)的鎖了惫企,我理解為情景鎖(另一個(gè)原因區(qū)分條件鎖 NSConditionLock)撕瞧,適用于一些特殊場景陵叽,其也遵循 NSLocking協(xié)議狞尔,也屬于互斥鎖

并且再其基礎(chǔ)上,新增了信號(hào)量功能 waitsignal巩掺,即 等待 和 釋放 偏序,使用方式和 semaphore 一樣,可以通過信號(hào)量控制線程的阻塞和釋放胖替,除此之外研儒,還多了一個(gè)broadcast,其可以解除所有因 wait 阻塞的線程

如下所示独令,使用 NSCondition 實(shí)現(xiàn)了一個(gè)生產(chǎn)者和消費(fèi)者的案例(生產(chǎn)者和消費(fèi)者都是同一撥人端朵,因此需要加鎖來實(shí)現(xiàn),而為了保證有錢了立刻買自己想買的東西燃箭,使用信號(hào)量冲呢,保證沒錢時(shí)阻塞等待,有錢時(shí)立即解放買買買)

其相當(dāng)于同時(shí)使用了NSLock 和 Semaphore 功能

#pragma mark --情景鎖NSCondition實(shí)現(xiàn)了NSLocking協(xié)議招狸,支持默認(rèn)的互斥鎖lock敬拓、unlock
- (void)NSCondition {
    _condition = [[NSCondition alloc] init];
}

//情景鎖還加入了信號(hào)量機(jī)制,wait和signal,可以利用其完成生產(chǎn)消費(fèi)者模式的功能
//生產(chǎn)者: 媽爸掙了一天的錢裙戏,儲(chǔ)蓄值增加
- (void)conditionPlusMoney {
    [_condition lock];
    //信號(hào)量增加乘凸,有儲(chǔ)蓄了,可以開放花錢功能了
    if (_money++ < 0) {
        [_condition signal];    //釋放第一個(gè)阻塞的線程
        //[_condition broadcast]; //釋放所有阻塞的線程
    }
    [_condition unlock];
}
//消費(fèi)者累榜,服務(wù)有儲(chǔ)蓄营勤,拿到錢時(shí)立即解鎖花錢技能(money--)
- (void)conditionSubMoney {
    [_condition lock];
    if (_money == 0) {
        //信號(hào)量減少阻塞,打算買東西壹罚,卻沒錢了葛作,停止花錢,等發(fā)工資再買東西
        [_condition wait];
    }
    //由于之前的wait,當(dāng)signal解鎖后,會(huì)走到這里啸盏,開始購買想買的東西烦味,儲(chǔ)蓄值--
    _money--;
    [_condition unlock];
}

NSConditionLock

NSConditionLock 被稱為條件鎖,其遵循 NSLocking 協(xié)議屡谐,即具備正常的互斥鎖功能

此外加入了 條件語句续担,為其核心功能赵誓,即滿足指定條件才會(huì)解鎖量瓜,因此算是一個(gè)重量級(jí)的鎖了司恳,其同時(shí)可以理解為 NSCondition 進(jìn)化版 ,如果你理解了 NSCondition生產(chǎn)者-消費(fèi)者模式绍傲,這個(gè)也會(huì)馬上就明白了其原理了

lockWhenCondition:(NSInteger)condition: 加鎖扔傅,當(dāng)條件condition為傳入的condition時(shí),方能解鎖

unlockWithCondition:(NSInteger)condition: 更新condition的值烫饼,并解鎖指定condition的鎖

下面使用一個(gè)異步隊(duì)列猎塞,來實(shí)現(xiàn)類似 NSOperation 設(shè)置的依賴關(guān)系,如下所示(打印結(jié)果1杠纵、4荠耽、3、2):

#pragma mark --條件鎖NSConditionLock,實(shí)現(xiàn)了NSLocking協(xié)議比藻,支持默認(rèn)的互斥鎖lock铝量、unlock
- (void)NSConditionLock {
    _conditionLock = [[NSConditionLock alloc] initWithCondition:1]; //可以更改值測(cè)試為0測(cè)試結(jié)果
    //加鎖,當(dāng)條件condition為傳入的condition時(shí)银亲,方能解鎖
    //lockWhenCondition:(NSInteger)condition
    //更新condition的值慢叨,并解鎖指定condition的鎖
    //unlockWithCondition:(NSInteger)condition
}

//多個(gè)隊(duì)列執(zhí)行條件鎖
//通過案例可以看出,通過條件鎖conditionLock可以設(shè)置線程依賴關(guān)系
//可以通過GCD設(shè)置一個(gè)具有依賴關(guān)系的任務(wù)隊(duì)列么
- (void)NSConditionLockUpdate {
    //創(chuàng)建并發(fā)隊(duì)列
    dispatch_queue_t queue = 
        dispatch_queue_create("測(cè)試NSConditionLock", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        if ([self->_conditionLock tryLockWhenCondition:1]) {
            NSLog(@"第一個(gè)");
            //默認(rèn)初始conditon位1务蝠,所有能走到這里
            //然后解鎖后拍谐,并設(shè)置初始值為4,解鎖condition設(shè)定為4的線程
            [self->_conditionLock unlockWithCondition:4];
        }else {
            [self->_conditionLock lockWhenCondition:0];
            NSLog(@"第一個(gè)other");
            [self->_conditionLock unlockWithCondition:4];
        }
    });
    //由于開始初始化的conditon值為1请梢,所以后面三個(gè)線程都不滿足條件
    //鎖定后直到condition調(diào)整為當(dāng)前線程的condition時(shí)方解鎖
    dispatch_async(queue, ^{
        //condition設(shè)置為3后解鎖當(dāng)前線程
        [self->_conditionLock lockWhenCondition:2];
        NSLog(@"第二個(gè)");
        //執(zhí)行完畢后解鎖赠尾,并設(shè)置condition為1,設(shè)置初始化默認(rèn)值毅弧,以便于下次使用
        [self->_conditionLock unlockWithCondition:1];
    });
    dispatch_async(queue, ^{
        //condition設(shè)置為3后解鎖當(dāng)前線程
        [self->_conditionLock lockWhenCondition:3];
        NSLog(@"第三個(gè)");
        //執(zhí)行完畢后解鎖气嫁,并設(shè)置condition為3,解鎖3
        [self->_conditionLock unlockWithCondition:2];
    });
    dispatch_async(queue, ^{
        //condition設(shè)置為4后解鎖當(dāng)前線程
        [self->_conditionLock lockWhenCondition:4];
        NSLog(@"第四個(gè)");
        //執(zhí)行完畢后解鎖够坐,并設(shè)置condition為3寸宵,解鎖3
        [self->_conditionLock unlockWithCondition:3];
    });
}

上面的流程可以大致簡化為下面幾步:

1.創(chuàng)建一個(gè)異步隊(duì)列,以便于添加后續(xù)的任務(wù)依賴

2.逐步添加子任務(wù)模塊元咙,分別在不同線程中梯影,其有明確的依賴關(guān)系,即執(zhí)行順序?yàn)?1庶香、4甲棍、3、2

3.使用 lockWhenCondition:開始設(shè)置依賴赶掖,將其任務(wù)解鎖的條件condition 設(shè)置為其特有的condition 號(hào)感猛,以便于解鎖

4.執(zhí)行任務(wù)時(shí)七扰,如果 NSCondition 中的 condition 參數(shù),與本線程設(shè)置的tCondition不一樣時(shí)陪白,阻塞線程颈走,等待 NSCondition 中的 condition 更改為指定值(通過 unlockWithCondition:更改condition值)解鎖

即:默認(rèn)初始化 condition 為 1,只有 任務(wù)1 能夠執(zhí)行咱士,當(dāng) 任務(wù)1 執(zhí)行 unlockWithCondition:4時(shí)立由,condition被設(shè)置為4, 阻塞的任務(wù)4解鎖,同理序厉,任務(wù)4執(zhí)行完畢后锐膜,將 condition 設(shè)置為 3 ,任務(wù)三解鎖,依次類推

5.最終根據(jù)設(shè)置的依賴關(guān)系脂矫,分別執(zhí)行 任務(wù)1枣耀、任務(wù)4霉晕、任務(wù)3庭再、任務(wù)2

pthread_mutex(recursive)

其為基于 pthread框架 的遞歸鎖,也是以 pthread互斥鎖為基礎(chǔ)實(shí)現(xiàn)的 遞歸鎖牺堰,即:同一個(gè)線程下拄轻,遞歸調(diào)用時(shí)加鎖,不會(huì)阻塞當(dāng)前線程伟葫,當(dāng)另一個(gè)線程到來時(shí)恨搓,會(huì)因?yàn)榈谝粋€(gè)線程加的鎖而阻塞

#pragma mark --pthread遞歸鎖
- (void)pthreadMutexRecursive {
    //初始化鎖的遞歸功能
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    //互斥鎖初始化時(shí),綁定遞歸鎖功能模塊
    pthread_mutex_init(&_pMutexLock, &attr);

    //使用完畢后在合適的地方銷毀筏养,例如dealloc
//    pthread_mutexattr_destroy(&attr);
//    pthread_mutex_destroy(&_pMutexLock);
}

//使用遞歸鎖斧抱,遞歸地時(shí)候回不停加鎖,如果使用普通的鎖早已經(jīng)形成死鎖渐溶,無法解脫
//遞歸鎖的存在就是在同一個(gè)線程中的鎖辉浦,不會(huì)互斥,只會(huì)互斥其他線程的鎖茎辐,從而避免死鎖
- (void)pthreadMutexRecursiveUpdate {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        static void (^recursiveBlock)(double count);
        recursiveBlock = ^(double count){
            pthread_mutex_lock(&self->_pMutexLock);
            if (count-- > 0) {
                self->_money++;
                recursiveBlock(count);
            }
            pthread_mutex_unlock(&self->_pMutexLock);
        };
        recursiveBlock(1000);
    });
}

NSRecursiveLock遞歸鎖

pthread_mutex(recursive)一樣宪郊,NSRecursiveLock 也是遞歸鎖,其遵循 NSLocking 協(xié)議拖陆,即除了遞歸鎖功能弛槐,還具備正常的互斥鎖功能

使用方式和 pthread_mutex(recursive)一樣如下所示

//使用遞歸鎖,遞歸地時(shí)候回不停加鎖依啰,如果使用普通的鎖早已經(jīng)形成死鎖乎串,無法解脫
//遞歸鎖的存在就是在同一個(gè)線程中的鎖,不會(huì)互斥速警,只會(huì)互斥其他線程的鎖叹誉,從而避免死鎖
- (void)NSRecursiveLockUpdate {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        static void (^recursiveBlock)(double count);
        recursiveBlock = ^(double count){
            [self->_recursive lock];
            //tryLock就不多介紹了艰争,和Pthread的類似,注意返回值即可
            //[self->_recursive tryLock];
            if (count-- > 0) {
                self->_money++;
                recursiveBlock(count);
            }
            [self->_recursive unlock];
        };
        recursiveBlock(1000);
    });
}
復(fù)制代碼

synchronized

synchronized 同步鎖桂对,即同步執(zhí)行甩卓,以此避免多線程同時(shí)操作同一塊代碼,基本上在各個(gè)平臺(tái)都會(huì)有其身影蕉斜,雖然效率最低逾柿,但由于使用使用簡單,深得大家喜愛

實(shí)現(xiàn)如下所示

#pragma mark --同步鎖synchronized
- (void)synchronized {
    //使用簡單宅此,直接對(duì)代碼塊加同步鎖机错,此代碼不會(huì)被多個(gè)線程直接執(zhí)行
    //可以間接理解為里面的任務(wù)被放到了一個(gè)同步隊(duì)列依次執(zhí)行(實(shí)際實(shí)現(xiàn)未知)
    @synchronized (self) {
        self->_money++;
    }
}

讀寫鎖

讀寫鎖 又被稱為 rw鎖或者 readwrite鎖,在 ios開發(fā)中雖能見到父腕,但確不是最常用的(一般是數(shù)據(jù)庫操作才會(huì)用到)弱匪。

具體操作為:多讀單寫,即璧亮,寫入操作只能串行執(zhí)行萧诫,且寫入時(shí),不能讀取枝嘶,而讀取需支持多線程操作帘饶,且讀取時(shí),不能寫入

相信大家也遇到過這樣的事群扶,系統(tǒng)的屬性設(shè)置了 auto參數(shù)及刻,字面意思為原子性操作,其實(shí)際未能保證屬性字段的多線程安全(由于舊值的賦值未加鎖竞阐,同時(shí)寫入時(shí)缴饭,會(huì)造成對(duì)象舊地址多次被release)

因此無論是想了解其實(shí)現(xiàn)方式,還是開發(fā)備用骆莹,都是有比較學(xué)習(xí)的

實(shí)現(xiàn)方式這里就提供兩種:pthread颗搂、GCD的barrier來實(shí)現(xiàn)

pthread讀寫鎖

使用前,需要先導(dǎo)入 pthread框架, 即 #import <pthread/pthread.h>

實(shí)現(xiàn)簡單汪疮,可以根據(jù)自己程序需要峭火,選擇鎖初始化的合適位置

//初始化pthread讀寫鎖
- (void)setupPhreadRW {
    pthread_rwlock_init(&_lock, NULL);
    //使用完畢銷毀讀寫鎖
    //pthread_rwlock_destroy(&_lock);
}

#pragma mark --通過pthread讀寫鎖來設(shè)置
- (void)setLock1:(NSString *)lock1 {
    pthread_rwlock_wrlock(&_lock);
    _lock1 = lock1;
    pthread_rwlock_unlock(&_lock);

}
- (NSString *)lock1 {
    NSString *lock1 = nil;
    pthread_rwlock_rdlock(&_lock);
    lock1 = [_lock1 copy]; //copy到新的地址,避免解鎖后拿到舊值
    pthread_rwlock_unlock(&_lock);
    return lock1;
}

GCD的barrier讀寫鎖

GCD的barrier柵欄功能相信大家都聽說過,即在一個(gè)新創(chuàng)建的隊(duì)列中智嚷,barrier功能可以保證卖丸,在他之前的異步隊(duì)列執(zhí)行完畢才指定barrier中間的內(nèi)容,且還能保證barrier執(zhí)行完畢后盏道,才之后barrier之后的任務(wù)稍浆,且一個(gè)隊(duì)列可以有多個(gè)barrier

因此此特性可以用于完成一個(gè)讀寫鎖功能,即 barrier的代碼塊作為 寫入操作模塊

如下代碼所示,由于需要引入 新創(chuàng)建隊(duì)列衅枫,雖然使用起來不是不如pthread優(yōu)秀嫁艇,但這種思想?yún)s可以再恰當(dāng)?shù)臅r(shí)候發(fā)芽出新樹苗

- (void)setupGCDRW {
    _queue = dispatch_queue_create("RWLockQueue", DISPATCH_QUEUE_CONCURRENT);
}

#pragma mark --通過GCD的barrier柵欄功能實(shí)現(xiàn)
//通過GCD的barrier柵欄功能實(shí)現(xiàn),缺點(diǎn)是需要借助自定義隊(duì)列實(shí)現(xiàn)弦撩,且get方法無法重寫系統(tǒng)的步咪,只能以回調(diào)的方式獲取值
//barrier功能使用global隊(duì)列會(huì)失效,全局隊(duì)列是無法阻塞的益楼,里面有系統(tǒng)的一些任務(wù)執(zhí)行
- (void)setLock2:(NSString *)lock2 {
    dispatch_barrier_async(_queue, ^{
        self->_lock2 = lock2;
    });
}
- (void)getLock2WithBlock:(void(^)(NSString *))block {
    dispatch_async(_queue, ^{
        block(self->_lock2);
    });
}

最后

相信看了這篇文章能給大家?guī)砀嗍肇?/p>

最后猾漫,你能根據(jù)讀寫鎖的特性,利用現(xiàn)有的鎖感凤,再寫出一個(gè)完整的讀寫鎖功能出來么!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末悯周,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子陪竿,更是在濱河造成了極大的恐慌禽翼,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件族跛,死亡現(xiàn)場離奇詭異闰挡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)庸蔼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門解总,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人姐仅,你說我怎么就攤上這事】萄危” “怎么了掏膏?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長敦锌。 經(jīng)常有香客問我馒疹,道長,這世上最難降的妖魔是什么乙墙? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任颖变,我火速辦了婚禮,結(jié)果婚禮上听想,老公的妹妹穿的比我還像新娘腥刹。我一直安慰自己,他們只是感情好汉买,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布衔峰。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪垫卤。 梳的紋絲不亂的頭發(fā)上威彰,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音穴肘,去河邊找鬼歇盼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛评抚,可吹牛的內(nèi)容都是我干的旺遮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盈咳,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼耿眉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鱼响,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤鸣剪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后丈积,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筐骇,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年江滨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了铛纬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唬滑,死狀恐怖告唆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晶密,我是刑警寧澤擒悬,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站稻艰,受9級(jí)特大地震影響懂牧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜尊勿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一僧凤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧元扔,春花似錦躯保、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溺忧。三九已至,卻和暖如春盯孙,著一層夾襖步出監(jiān)牢的瞬間鲁森,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工振惰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歌溉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓骑晶,卻偏偏與公主長得像痛垛,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桶蛔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • 前言 開發(fā)中引入了異步和多線程的來提高程序性能仔雷,也就意味著線程安全成為了多線程的一個(gè)障礙蹂析,因此線程鎖應(yīng)運(yùn)而生,而鎖...
    iOS鑫閱讀 912評(píng)論 0 4
  • 簡介 在使用多線程的時(shí)候多個(gè)線程可能會(huì)訪問同一塊資源碟婆,這樣就很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全等問題电抚。我們常常會(huì)使用一些...
    遠(yuǎn)方竹葉閱讀 1,002評(píng)論 0 8
  • 轉(zhuǎn)鏈接:https://juejin.im/post/5d395318f265da1b8608ca98 自旋鎖 O...
    DL是誰閱讀 483評(píng)論 0 0
  • 我的博客, 各位看官有時(shí)間賞光 鎖 我們?cè)谑褂枚嗑€程的時(shí)候多個(gè)線程可能會(huì)訪問同一塊資源,這樣就很容易引發(fā)數(shù)據(jù)錯(cuò)亂和...
    VIC_LI閱讀 1,526評(píng)論 0 36
  • pthread_mutex_tpthread_rwlock_tpthread_cond_tdispatch_sem...
    MiniCoder閱讀 137評(píng)論 0 2