The lock of the synchronization thread in the Objective-c

Source: Internet
Author: User
Tags pthread mutex

Overview
In multi-threaded programming, we often encounter multiple threads accessing shared resources at the same time. We need to avoid this by synchronizing threads. That is, lock the thread.
Because Objective-C is a superset of C. Strictly speaking, it is a true superset. Therefore, pthread mutex in C language can also be used in Objective-C, but Objective-C defines its own lock object and lock protocol, so this article introduces locks in Objective-C.

NSLock NSLocking protocol
@protocol NSLocking
-(void) lock;
-(void) unlock;
@end
The following types of locks, NSLock, NSConditionLock, and NSRecursiveLock, all implement this protocol to uniformly lock and unlock with lock and unlock.

NSLock use
    NSLock * lock = [[NSLock alloc] init];
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        [lock lock]; // Get lock
        NSLog (@ "lock success");
        sleep (5);
        NSLog (@ "sleep end");
        [lock unlock]; // Abandon the lock acquired before
    });
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        [lock lock]; // Obtain a lock, if you can't get it, block the current thread until you get the lock
        NSLog (@ "remove lock");
        [lock unlock]; // Abandon the acquired lock
    });
Output result

 lock success
 sleep end
 remove lock
When the NSLock object sends a lock message, first check whether the lock can be obtained. If the lock is being used in other threads at this time, then the current thread will be blocked until the other threads have used the lock. After the lock is unlocked, the current lock can be obtained. The thread is reacquired and the thread resumes. If the lock cannot be acquired, the thread will always block, so the two methods lock and unlock must appear in pairs. Of course, there are thread methods tryLock and lockBeforeDate that do not block calling the lock:

tryLock
tryLock tries to acquire the lock, if it can't get NO, it returns YES, otherwise it won't block the thread calling it

    NSLock * lock = [[NSLock alloc] init];
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        [lock lock]; // Get lock
        NSLog (@ "lock success");
        sleep (5);
        NSLog (@ "sleep end");
        [lock unlock]; // Abandon the lock acquired before
    });
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        if ([lock tryLock]) // Try to acquire the lock, if the acquisition fails to return NO, the thread will not be blocked
        {
            NSLog (@ "remove lock");
            [lock unlock];
        }
        else {
            NSLog (@ "obtain failure");
        }
    });
Output result

lock success
obtain failure
sleep end
The acquisition failed because the current lock is being used in another thread. If the current lock is not used then YES is returned.
lockBeforeDate
lockBeforeDate blocks the calling thread, if the lock cannot be acquired within a given time then gives up acquiring and resumes the thread.

    NSLock * lock = [[NSLock alloc] init];
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        [lock lock]; // Get lock
        NSLog (@ "lock success");
        sleep (5);
        NSLog (@ "sleep end");
        [lock unlock]; // Abandon the lock acquired before
    });
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        NSDate * date = [[NSDate alloc] initWithTimeIntervalSinceNow: 3];
        if ([lock lockBeforeDate: date]) // Try to acquire a lock in the next 3s and block the thread, if the recovery thread cannot be obtained within 3s
        {
            NSLog (@ "remove lock");
            [lock unlock];
        }
        else {
            NSLog (@ "obtain failure");
        }
    });
Output result

 lock success
 obtain failure
 sleep end
NO if not available within 3s, otherwise YES

@synchronized
synchronized provides a locking and unlocking mechanism for an object. synchronized will block the calling thread

    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        @synchronized (self) {
            [self logging: @ "lock success"];
            sleep (5);
            [self logging: @ "sleep end"];
        }
    });
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        @synchronized (self) // Wait to execute the following code after the execution of the above thread is completed, and the current thread will be blocked at this time
        {
            [self logging: @ "remove lock"];
        }
    });
Output result

 lock success
 sleep end
 remove lock
The above locking of its own object will not execute the following locked code until the first GCD has been completely executed.
note
Objective-C classes themselves are objects, so you can use synchronized for these class objects, and at this time, thread synchronization is performed on the entire object type. E.g:

    @synchronized ([self class]) {
    }
NSConditionLock
NSConditionLock conditional lock. When acquiring the lock, it must be the same as the unlocking condition previously set. Otherwise, the current thread will block until the conditions are consistent.
The most typical example is the producer-consumer scenario. When the data is empty, the producer produces data. At this time, the consumer cannot obtain the data. After the producer produces the data, the consumer processes the data until the consumer processes all the data. It is empty again, at this time the producer continues to produce data. The sample code is as follows:

    enum {NO_DATA_IN_QUEUE = 0, HAS_DATA_IN_QUEUE};
    NSConditionLock * conditionLock = [[NSConditionLock alloc] initWithCondition: NO_DATA_IN_QUEUE];

    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        while (YES) {
            [conditionLock lockWhenCondition: NO_DATA_IN_QUEUE];
            NSLog (@ "insert data");
            sleep (3);
            NSLog (@ "intset success");
            [conditionLock unlockWithCondition: HAS_DATA_IN_QUEUE];
        }
    });
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {
        while (YES) {
            [conditionLock lockWhenCondition: HAS_DATA_IN_QUEUE];
            NSLog (@ "delete data");
            sleep (3);
            NSLog (@ "delete success");
            [conditionLock unlockWithCondition: NO_DATA_IN_QUEUE];
        }
    });
Output results:

 insert data
 intset success
 delete data
 delete success
 insert data
 intset success
 delete data
 delete success
 ...
NSRecursiveLock
NSRecursiveLock recursive lock. When we synchronize a thread with a recursive function, the lock will be acquired multiple times in the same thread, resulting in thread deadlock. NSRecursiveLock can acquire the lock multiple times in the same thread without deadlock.

NSRecursiveLock * recursiveLock = [[NSRecursiveLock alloc] init];
    dispatch_async (dispatch_get_global_queue (0, 0), ^ {

       static void (^ recursive) (int count);
        recursive = ^ (int count) {
            [recursiveLock lock];
            if (count> 0) {
                NSLog (@ "success lock");
                sleep (3);
                recursive (-count);
            }
            [recursiveLock unlock];
        };
        recursive (3);

    });
In the above case, if you use NSLock to continue to acquire the lock without unlocking it, it will cause a deadlock and cause the threads to be consistently blocked.

NSDistributedLock
NSDistributedLock is a mutex solution in Mac multi-threaded development, so I won't introduce more here.

Synchronous thread locks in Objective-C

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.