“This is the 17th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

NSConditionLock

NSConditionLock concept

NSConditionLock encapsulates NSCondition and controls locking and unlocking through condition variables, so as to block and wake up the thread

NSConditionLock conditionlock conditionlockNSLockingAgreement >

  • If no other thread holds the lock, but the condition inside the lock is not equal to the value passed in, the following line cannot hold the lock, enters the wait state, and blocks the thread. If the condition inside the lock is equal to the value passed in, and no other thread is holding the lock, the code area is entered. With the lock set, any other thread will wait for its code to complete until it unlocks

    - (void)lockWhenCondition:(NSInteger)condition;
    Copy the code
  • Unlocks the operation while setting the internal condition to the passed value

    - (void)unlockWithCondition:(NSInteger)condition;
    Copy the code
  • If the condition value of the lock is equal to the value passed in, the lock is successful. Otherwise, NO is returned and the thread is not blocked

    - (BOOL)tryLockWhenCondition:(NSInteger)condition;
    Copy the code
  • When the conditional value of the lock is equal to the value passed in, YES is returned on success, otherwise NO is returned on failure, and the thread is blocked before time

    - (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;
    Copy the code

NSConditionLock Common scenarios

NSConditionLock can be used to resolve the callback order scenario

- (void)viewDidLoad{
    [super viewDidLoad];

    NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:0];

    / / thread 1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [lock lockWhenCondition:1];
        NSLog(@Thread 1 "");
        [lock unlock];
    });

    / / thread 2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(4);// To ensure that thread 2 code is executed later
        
        if ([lock tryLockWhenCondition:0]) {
            NSLog(@Thread 2 "");
            [lock unlockWithCondition:1];
            NSLog(@"Thread 2 unlocked successfully");
        } else {
            NSLog(@Thread 2 failed to lock); }});3 / / thread
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(2);// To ensure that thread 3 code is executed later
        
        if ([lock tryLockWhenCondition:2]) {
            NSLog(@"Thread 3");    
            [lock unlock];
            NSLog(@"Thread 3 unlocked successfully");
        } else {
            NSLog(@Thread 3 failed to lock); }}); }Copy the code

log:

1. Initialize NSConditionLock and set condition to 0

2, when thread 1 calls [LOCK lock whenCondition :1], it will enter the wait state because the current condition is not met, and will block the thread

3, thread 3 calls [lock tryLockWhenCondition:2] and prints: thread 3 failed to lock because the current condition is not met but the thread is not blocked

Thread 2 calls [Lock tryLockWhenCondition:0], because when the lock condition is equal to the value passed in, it prints thread 2. When the print is complete, it calls [Lock unlockWithCondition:1], and the condition is set to 1. And sends a boradcast, at which point thread 1 receives the current signal, wakes up thread 1 and finishes printing thread 1