NSCondition、NSConditionLock

一,NSCondition

1,簡(jiǎn)介:

NSCondition

條件鎖,顧名思義,就是滿足某些條件才會(huì)開(kāi)鎖。NSCondition,可以確保線程僅在滿足特定條件時(shí)才能獲取鎖。一旦獲得了鎖并執(zhí)行了代碼的關(guān)鍵部分,線程就可以放棄該鎖并將關(guān)聯(lián)條件設(shè)置為新的條件。條件本身是任意的:可以根據(jù)應(yīng)用程序的需要定義它們。

NSCondition對(duì)象實(shí)際上作為一個(gè)鎖和一個(gè)線程檢查器:鎖主要為了當(dāng)檢測(cè)條件時(shí)保護(hù)數(shù)據(jù)源,執(zhí)行條件引發(fā)的任務(wù);線程檢查器主要是根據(jù)條件決定是否繼續(xù)運(yùn)行線程,即線程是否被阻塞。通俗的說(shuō),也就是條件成立,才會(huì)執(zhí)行鎖住的代碼。條件不成立時(shí),線程就會(huì)阻塞,直到另一個(gè)線程向條件對(duì)象發(fā)出信號(hào)解鎖為止。

2,方法:

//一般用于多線程同時(shí)訪問(wèn)、修改同一個(gè)數(shù)據(jù)源,保證在同一時(shí)間內(nèi)數(shù)據(jù)源只被訪問(wèn)、修改一次,其他線程的命令需要在lock 外等待,只到unlock ,才可訪問(wèn)
[condition lock];

//與lock 同時(shí)使用
[condition unlock];

//讓當(dāng)前線程處于等待狀態(tài)
[condition wait];

//CPU發(fā)信號(hào)告訴線程不用在等待,可以繼續(xù)執(zhí)行
[condition signal];

3,示例:

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSCondition *condition;
@property (nonatomic, strong) NSMutableArray *collector;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.condition = [[NSCondition alloc] init];
    self.collector = [[NSMutableArray alloc] initWithCapacity:0];
    
    [self test];
}

- (void)test {
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT), ^{
        while (true) {
            [weakSelf.condition lock];
            if (weakSelf.collector.count > 0 ) {
                [weakSelf.condition wait];
            }
            [weakSelf.collector addObject:@"商品"];
            NSLog(@"生產(chǎn):商品");
            [weakSelf.condition signal];
            [weakSelf.condition unlock];
        }
    });
    
    dispatch_async(dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT), ^{
        while (true) {
            [weakSelf.condition lock];
            if (weakSelf.collector.count == 0 ) {
                [weakSelf.condition wait];
            }
            
            NSString *item = [weakSelf.collector objectAtIndex:0];
            NSLog(@"消費(fèi):%@",item);
            [weakSelf.collector removeObjectAtIndex:0];
            [weakSelf.condition signal];
            [weakSelf.condition unlock];
        }
    });
}

@end

4,解析:
當(dāng)collector.count == 0時(shí), 消費(fèi)線程condition調(diào)用wait進(jìn)入等待狀態(tài)。生產(chǎn)線程生產(chǎn)商品后condition調(diào)用signal,釋放信號(hào),使處于等待的消費(fèi)線程喚醒。這時(shí)collector.count > 0,生產(chǎn)線程condition調(diào)用wait進(jìn)入等待狀態(tài)。消費(fèi)線程消費(fèi)商品后調(diào)用signal,釋放信號(hào),使生產(chǎn)線程喚醒開(kāi)始生產(chǎn)...,從而不斷生產(chǎn)、消費(fèi)、生產(chǎn)、消費(fèi)的流程。

一,NSConditionLock

1,簡(jiǎn)介:

NSConditionLock對(duì)NSCondition又做了一層封裝,自帶條件探測(cè),能夠更簡(jiǎn)單靈活的使用。

2,示例:

NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:2];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
       [conditionLock lockWhenCondition:1];
       NSLog(@"線程1");
       [conditionLock unlockWithCondition:0];
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
       [conditionLock lockWhenCondition:2];
       NSLog(@"線程2");
       [conditionLock unlockWithCondition:1];
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       [conditionLock lock];
       NSLog(@"線程3");
       [conditionLock unlock];
    });

3,解析:

線程1調(diào)用[NSConditionLock lockWhenCondition:],此時(shí)此刻因?yàn)椴粷M足當(dāng)前條件,所以會(huì)進(jìn)入等待狀態(tài)。此時(shí)當(dāng)前的線程3調(diào)用[NSConditionLock lock:],本質(zhì)上是調(diào)用 [NSConditionLock lockBeforeDate:],這里不需要比對(duì)條件值,所以線程 3會(huì)打印。接下來(lái)線程2執(zhí)行[NSConditionLock lockWhenCondition:],因?yàn)闈M足條件值,所以線程2會(huì)打印,打印完成后會(huì)調(diào)用[NSConditionLock unlockWithCondition:],這個(gè)時(shí)候?qū)l件設(shè)置為 1,并發(fā)送boradcast, 此時(shí)線程1接收到當(dāng)前的信號(hào),喚醒執(zhí)行并打印。
自此當(dāng)前打印為 線程 3->線程 2 -> 線程 1。
[NSConditionLock lockWhenCondition:]:這里會(huì)根據(jù)傳入的condition 值和value值進(jìn)行對(duì)比,如果不相等,這里就會(huì)阻塞。而[NSConditionLock unlockWithCondition:]會(huì)先更改當(dāng)前的value值,然后調(diào)用boradcast,喚醒當(dāng)前的線程。

一,總結(jié)

相同點(diǎn):

1,都是互斥鎖
2,通過(guò)條件變量來(lái)控制加鎖、釋放鎖,從而達(dá)到阻塞線程、喚醒線程的目的

不同點(diǎn):

1,NSCondition是基于對(duì)pthread_mutex的封裝,而NSConditionLock是對(duì)NSCondition做了一層封裝
2,NSCondition是需要手動(dòng)讓線程進(jìn)入等待狀態(tài)阻塞線程、釋放信號(hào)喚醒線程
NSConditionLock則只需要外部傳入一個(gè)值,就會(huì)依據(jù)這個(gè)值進(jìn)行自動(dòng)判斷是阻塞線程還是喚醒線程

參考鏈接:
http://www.itdecent.cn/p/0c981352b6d2
http://www.itdecent.cn/p/53a04d5982fe
http://www.itdecent.cn/p/5d20c15ae690

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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