iOS線程同步鎖

當(dāng)我們涉及多線程開(kāi)發(fā)時(shí)就必然涉及線程間的數(shù)據(jù)安全問(wèn)題。iOS中線程同步技術(shù)的方案之一就是給數(shù)據(jù)上鎖。線程鎖有很多種,如下所示:

os_unfair_lock
pthread_mutex
dispatch_semaphore
dispatch_queue(DISPATCH_QUEUE_SERIAL)
NSLock
NSRecursiveLock
NSCondition
NSConditionLock
@synchronized

1.os_unfair_lock

導(dǎo)入頭文件

#import <os/lock.h>

用法如下:

    //創(chuàng)建鎖
    os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
    //嘗試加鎖,添加成功返回true,添加失敗返回false
    bool r = os_unfair_lock_trylock(&lock);
    //強(qiáng)制加鎖
    os_unfair_lock_lock(&lock);
    // 解鎖
    os_unfair_lock_unlock(&lock);

其中os_unfair_lock_trylock方法與os_unfair_lock_lock方法,我們使用一個(gè)加鎖即可。

2.pthread_mutex

導(dǎo)入頭文件

#import <pthread/pthread.h>

用法如下:

    //創(chuàng)建鎖屬性,也可不設(shè)置鎖屬性
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    /*
     * Mutex type attributes
     */
    //    #define PTHREAD_MUTEX_NORMAL        0
    //    #define PTHREAD_MUTEX_ERRORCHECK    1
    //    #define PTHREAD_MUTEX_RECURSIVE        2
    //    #define PTHREAD_MUTEX_DEFAULT        PTHREAD_MUTEX_NORMAL
    //PTHREAD_MUTEX_RECURSIVE設(shè)置為該屬性時(shí),為遞歸鎖,在遞歸函數(shù)中使用,保證遞歸函數(shù)調(diào)用僅一個(gè)線程
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);

    //創(chuàng)建鎖
    pthread_mutex_t mutexLock;
    //可設(shè)置屬性
    //    pthread_mutex_init(&mutexLock, &attr);
    pthread_mutex_init(&mutexLock, NULL);
    //嘗試加鎖,返回1代表加鎖成功
    //            int r = pthread_mutex_trylock(&mutexLock);
    //強(qiáng)制加鎖
    pthread_mutex_lock(&mutexLock);
    // 解鎖
    pthread_mutex_unlock(&mutexLock);
    //銷(xiāo)毀鎖
    pthread_mutexattr_destroy(&attr);
    pthread_mutex_destroy(&mutexLock);

pthread_mutex也可以創(chuàng)建條件鎖,當(dāng)我們遇到以下情況時(shí)可以使用條件鎖:


image.png

開(kāi)始執(zhí)行任務(wù)1和任務(wù)2,但是任務(wù)1依賴(lài)于任務(wù)2,必須任務(wù)2執(zhí)行完畢才執(zhí)行任務(wù)1,我們可以在任務(wù)1前增加條件鎖,在任務(wù)2完成后打開(kāi)條件鎖,就滿足我們的業(yè)務(wù)開(kāi)發(fā)需求。
相關(guān)代碼方法如下:

    //創(chuàng)建鎖
    pthread_mutex_t mutexLock;
    //可設(shè)置屬性
    pthread_mutex_init(&mutexLock, NULL);
    
    //初始化條件
    pthread_cond_t cond;
    pthread_cond_init(&cond, NULL);

    //進(jìn)入休眠,等待喚醒
    pthread_cond_wait(&self->_cond, &self->_mutexLock);

    //激活所有等待該條件的線程
    //        pthread_cond_broadcast(&self->_cond);
    //激活一個(gè)等待該條件的線程
    pthread_cond_signal(&self->_cond);
    //銷(xiāo)毀資源
    pthread_mutex_destroy(&(self->_mutexLock));
    pthread_cond_destroy(&self->_cond);

3.dispatch_semaphore

信號(hào)量的使用
GCD提供了信號(hào)量函數(shù),提供我們進(jìn)行線程安全操作,當(dāng)信號(hào)量為0時(shí)等待操作,信號(hào)量大于0是,繼續(xù)執(zhí)行操作,,主要流程如下:
1、創(chuàng)建信號(hào)量對(duì)象,確定信號(hào)初始值
2、開(kāi)始執(zhí)行操作前檢查是否需要等待,執(zhí)行函數(shù)dispatch_semaphore_wait,如果當(dāng)前的信號(hào)量為0則阻塞,等待信號(hào)量大于0時(shí)繼續(xù)執(zhí)行,執(zhí)行函數(shù)完畢會(huì)使信號(hào)量減一。當(dāng)一個(gè)任務(wù)執(zhí)行完畢時(shí)我們需要調(diào)用dispatch_semaphore_signal函數(shù),告訴系統(tǒng)一個(gè)任務(wù)執(zhí)行完畢,調(diào)用后會(huì)使信號(hào)量加1。dispatch_semaphore_wait和dispatch_semaphore_signal函數(shù)應(yīng)當(dāng)成對(duì)存在,有特別需求也可以不成對(duì)存在。當(dāng)初始信號(hào)量為1時(shí),我們可以用作線程安全鎖進(jìn)行使用,代碼如下:

- (void)dispatch_semaphore {
    dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(3);
    for (int i = 0; i < 10; i++) {
        dispatch_semaphore_wait(semaphore_t, DISPATCH_TIME_FOREVER);
        dispatch_async(self.concurrent_queue, ^{
            int t = rand() % 5;
            sleep(t);
            NSLog(@"dispatch_semaphore===%d===%@===%d",i,[NSThread currentThread],t);
            dispatch_semaphore_signal(semaphore_t);
        });
    }
    NSLog(@"end");
}

4.dispatch_queue

創(chuàng)建串形隊(duì)列相當(dāng)于加上了安全鎖
代碼如下

dispatch_queue_create("", DISPATCH_QUEUE_SERIAL)

5.NSLock

NSLock是對(duì)mutex的面相對(duì)象封裝,使用比較簡(jiǎn)單。
代碼如下:

    //創(chuàng)建對(duì)象
    NSLock *lock = [[NSLock alloc] init];
    //上鎖
    [lock lock]
    //解鎖
    [lock unlock];

6.NSRecursiveLock

NSRecursiveLock是mutex遞歸鎖的面向?qū)ο蠓庋b,使用簡(jiǎn)單。代碼如下:

    //創(chuàng)建對(duì)象
    NSRecursiveLock* lock = [[NSRecursiveLock alloc] init];
    //上鎖
    [lock lock];
    //解鎖
    [lock unlock];

7.NSCondition

NSCondition是對(duì)mutex和cond的封裝,代碼如下:

    //創(chuàng)建對(duì)象
    NSCondition *condition = [[NSCondition alloc] init];
    //激活所有等待該條件的線程
    //[self.condition broadcast];
    //激活一個(gè)等待該條件的線程
    [self.condition signal];
    //進(jìn)入休眠,等待喚醒
    [self.condition wait];

8.NSConditionLock

NSConditionLock是對(duì)NSCondition的進(jìn)一步封裝,可以設(shè)置具體的條件值。用法如下:

    //創(chuàng)建條件2的鎖
    NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:2];
    self.conditionLock = lock;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //等待條件1
        [self.conditionLock lockWhenCondition:1];
        NSLog(@"1");
        //打開(kāi)條件3
        [self.conditionLock unlockWithCondition:3];
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //等待條件4
        [self.conditionLock lockWhenCondition:4];
        NSLog(@"2");
        //打開(kāi)條件1
        [self.conditionLock unlockWithCondition:1];
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //等待條件2
        [self.conditionLock lockWhenCondition:2];
        NSLog(@"3");
        //打開(kāi)條件4
        [self.conditionLock unlockWithCondition:4];
    });

打印順序?yàn)?、2、1

9.synchronized

synchronized使用很簡(jiǎn)單,把代碼寫(xiě)在大括號(hào)里面就行。

    @synchronized (<#token#>) {
                <#statements#>
    }

例如:

    @synchronized (self) {
      self.count = self.count + 1;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 多線程系列篇章計(jì)劃內(nèi)容:iOS多線程編程(一) 多線程基礎(chǔ)[https://juejin.im/post/6890...
    賣(mài)饃工程師閱讀 962評(píng)論 0 3
  • 原創(chuàng):知識(shí)點(diǎn)總結(jié)性文章創(chuàng)作不易,請(qǐng)珍惜,之后會(huì)持續(xù)更新,不斷完善個(gè)人比較喜歡做筆記和寫(xiě)總結(jié),畢竟好記性不如爛筆頭哈...
    時(shí)光啊混蛋_97boy閱讀 974評(píng)論 0 2
  • 為什么要線程同步 我們?cè)谑褂枚嗑€程的時(shí)候,可能會(huì)遇到多個(gè)線程同時(shí)訪問(wèn)同一個(gè)數(shù)據(jù)導(dǎo)致數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)不安全的問(wèn)題,所以...
    浪的出名閱讀 1,113評(píng)論 1 3
  • 什么會(huì)給多線程的安全造成隱患? 有了多線程技術(shù)支持,我們可以并發(fā)的進(jìn)行多個(gè)任務(wù),因此同一塊資源就有可能在多個(gè)線程中...
    RUNNING_NIUER閱讀 3,421評(píng)論 6 32
  • 一、多線程的安全隱患 資源共享一塊資源可能會(huì)被多個(gè)線程共享,也就是多個(gè)線程可能會(huì)訪問(wèn)同一塊資源比如多個(gè)線程訪問(wèn)同一...
    happy神悅閱讀 399評(píng)論 0 0

友情鏈接更多精彩內(nèi)容