First, what is a lock, why to use a lock?

Lock: (gate used to control the gate in the home, not your family don’t let into, well) in the iOS development, we often mention lock, unlock, what lock, don’t worry, we said to lock in iOS must mention the ticket system, if the library has 100 tickets, now has 10 window in the ticket, if the same time, 10 window to see how many votes in the Treasury, is back to 100, that is to say, every window can buy 100 pieces, only one when the garage, and 10 window to query shows a, but 10 window not dictate who sell this ticket, so can go to sell, then the problem comes, 10 window is someone wants to buy a ticket, At the same time, I started to query the ticket purchase. Ideally, the ticket purchase result will return at the same time. Then all 10 people show that they have bought the ticket successfully, but there is only one ticket. Our key to lock, is to lock, lock the effect is, walk a plank bridge, and is a person must go at a time, behind the queue, such as the front of the people over, behind again. Our program and, if multiple local access to the same content at the same time, and make changes, at the same time to read the memory function, then, get value is not determined, is not what we want, so we in some blocks of code lock, when object access, lock, and when he finished his visit, and then unlock, others go to visit, chains, When other objects come to visit, it’s just a matter of waiting.

Why locks: For data security, it’s that simple.

What are the locks in iOS development?

There are eight kinds of locks in iOS development, but we only use four or five kinds of locks frequently. Therefore, the main object of today is the commonly used locks, and other kinds of locks can be introduced. If you want to know more about them, I recommend the following kinds of locks we commonly use: NSLock, NSConditionLock, NSRecursiveLock, NSCondition, @synchronized, dispatch_semaphore.

NSLock lock, this lock is usually developed when the need to pay attention to, although also to protect code snippets or data access to lock effect, but!! , try using code found that his lock unlock or there is a problem, if you are in the same thread, for more than two consecutive contains two lock, the lock and then lock first, then to turn into a permanent lock, if you are the child thread, so the child thread is blocked, if you are in the main thread, so the main thread is blocked. NSLock If the lock fails when you call the lock or unlock method, you will enter waiting state after 1s. Therefore, the development must pay attention to the lock and unlock corresponding NSLock. Now let’s look at my test code. I’m doing this on the main thread, just for demonstration purposes.

int a = 0; NSLock *lock = [[NSLock alloc] init]; for (int i = 0; i < 10; i++) { [lock lock]; NSLog(@" lock succeeded "); sleep(1); a++; [lock unlock]; NSLog(@" unlocked successfully "); } NSLog(@"---%d",a);Copy the code

Initialize the NSLock lock, then declare an integer a, use a for loop, lock each time the loop comes in, then sleep the program for 1s, then increments the integer A, then unlocks, and print the value of A when the loop is finished. All process is normal, but when I in front of the for loop, to perform the first lock operation, then thread card died, because of the for loop and a subsequent lock operation, but it has already been locked, subsequent attempts to lock lock, lock failure after 1 s, in waiting, waiting to be awakened again, but I just locked, not unlock, So it’s always waiting, and it’s always waiting to block the thread. Because NSLock is not a recursive lock, it only allows pairing of locks before unlocking. Or undertake first unlock, add lock unlock again.

Since NSLock cannot recursively lock, we can solve this problem with NSRecursiveLock, which supports recursivelock unlocking, or with synchronized.

__block int a = 0; NSRecursiveLock *lock = [[NSRecursiveLock alloc] init]; [lock lock]; for (int i = 0; i < 10; i++) { [lock lock]; NSLog(@" lock succeeded "); sleep(1); a++; [lock unlock]; NSLog(@" unlocked successfully "); } [lock unlock]; NSLog(@"---%d",a); __block int a = 0; for (int i = 0; i < 10; I++) {@synchronized (self) {NSLog(@synchronized); a++; NSLog(@" unlocked successfully "); } } NSLog(@"---%d",a);Copy the code

“Dispatch_semaphore_create” (long value) creates a semaphore whose value must be greater than or equal to 0, otherwise NULL is returned. But if you set the semaphore to zero, then the block of asynchronous code waiting to receive the signal will wait until the timeout is set before continuing to execute the rest of the code. The second line, which is more common, is to create a wait period. And then we have two asynchronous functions, and in the asynchronous function dispatch_semaphore_wait is waiting for a signal, waiting for a signal to be received, and if a signal is received, proceed to the next step, and if we execute this code now, two logs are printed out very quickly, But if we call the first asynchronous function dispatch_semaphore_signal(semaphore); When we run the program, we will find that after printing the first log, we are waiting for the signal to start executing the code block of the second asynchronous function until the given timeout time, which is set to 10 seconds.

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); dispatch_time_t overTime = dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC); dispatch_async(dispatch_get_global_queue(0, 0), ^{ dispatch_semaphore_wait(semaphore, overTime); NSLog(@" thread 1 starts execution "); dispatch_semaphore_signal(semaphore); }); dispatch_async(dispatch_get_global_queue(0, 0), ^{ dispatch_semaphore_wait(semaphore, overTime); NSLog(@" thread 2 starts execution "); dispatch_semaphore_signal(semaphore); });Copy the code

Dispatch_semaphore_wait and dispatch_semaphore_signal are similar to THE LOCK and unlock methods of NSLock, but dispatch_semaphore_t can communicate between different threads.