Common locks in iOS

Source: Internet
Author: User

The security hidden trouble of multithreading

A resource may be shared by multiple threads, which means that multiple threads may access the same resource.

For example, multiple threads manipulate the same object at the same time, the same variable.

When multiple threads access the same piece of resources, data confusion and data security problems can easily arise.

For example, a ticket question:

#import "ViewController.h" @interface Viewcontroller () @property (assign, nonatomic) Nsinteger maxcount;@ End@implementation viewcontroller-(void) viewdidload {    [super viewdidload];

_maxcount =; Thread 1 [nsthread detachnewthreadselector: @selector (Run) totarget:self Withobject:nil]; Thread 2 [nsthread detachnewthreadselector: @selector (Run) totarget:self Withobject:nil]; } -(void) run{ while (1) { if (_maxcount > 0) { //pause for a period of time [Nsthread sleepfortimeinterval:0.002]; _maxcount--; NSLog (@ "sold a ticket-%ld-%@", _maxcount,[nsthread CurrentThread]); } else{ NSLog (@ "ticket sold Out"); Break;}}}

Output Result:

It can be seen that when multiple threads access the same data at the same time, it is very easy to get the phenomenon of data confusion and resource contention.

1. @synchronized (Lock Object) {//code requiring locking} to resolve

Mutex, which uses the technique of thread synchronization. Lock code needs to be as few as possible, this lock?? Objects need to remain the same object in multiple threads.

Advantage: It is not necessary to display the creation of the lock object, you can implement the lock mechanism.

Disadvantage: An implicit exception-handling routine is added to protect the code, which automatically releases the mutex when the exception is thrown, consuming system resources.

-(void) run{while    (1) {        //Use self in this case, or a global object that has a lock inside each object        @synchronized (self) {            if (_maxcount > 0 {//Pause for a period of                time                [Nsthread sleepfortimeinterval:0.002];                _maxcount--;                NSLog (@ "sold a ticket-%ld-%@", _maxcount,[nsthread CurrentThread]);            } else{                NSLog (@ "ticket sold Out");                Break;}}}}    

Output Result:

2. Nslock

In the cocoa Framework, Nslock implements a simple mutex, and the interfaces of all locks (including nslock) are actually defined by the Nslocking protocol, which defines the lock (locking) and unlock (unlock) methods.

The lock method cannot be called multiple times, causing a deadlock.

We use Nslock to solve the above problem:

 #import "ViewController.h" @interface Viewcontroller () @property (Assign, nonatomic) Nsinteger MaxCount; @property (Strong, nonatomic) Nslock *lock;    Data is @end@implementation viewcontroller-(void) viewdidload {[Super viewdidload];        Additional setup after loading the view, typically from a nib.        _maxcount = 20;        _lock = [[Nslock alloc] init];        Thread 1 [nsthread detachnewthreadselector: @selector (Run) totarget:self Withobject:nil];    Thread 2 [nsthread detachnewthreadselector: @selector (Run) totarget:self Withobject:nil];        }-(void) run{while (1) {//locking [_lock lock];            if (_maxcount > 0) {//pause for a period of time [Nsthread sleepfortimeinterval:0.002];            _maxcount--;        NSLog (@ "sold a ticket-%ld-%@", _maxcount,[nsthread CurrentThread]);            }else{NSLog (@ "ticket sold out");        Break    }//Release lock [_lock unlock]; }}

Output Result:

3. Nsrecursivelock Recursive lock

If the lock is used in the loop, it can easily cause a deadlock. The following code, in the recursive block, multiple calls to the lock method, the lock will be multiple times lock, so itself is blocked.

_lock = [[Nslock alloc] init];        Thread 1    dispatch_async (dispatch_queue_create (NULL, 0), ^{        static void (^testmethod) (int);        TestMethod = ^ (int value)        {            [_lock lock];            if (value > 0)            {                [nsthread sleepfortimeinterval:1];                NSLog (@ "Execute once Oh");                TestMethod (value--);            }            NSLog (@ "Whether to execute here");            [_lock unlock];        };                TestMethod (5);    });

Output content:

2017-12-12 11:39:50.253155+0800 nslock[1353:158620] Execute once OH

Change Nslock to nsrecursivelock here to solve the problem:

A lock defined by the Nsrecursivelock class can be locked multiple times on the same thread without causing a deadlock. A recursive lock tracks how many locks it will be, and each successful lock must balance the call unlock operation. Only when all locked and unlocked operations are balanced does the lock really get released to other threads.

_lock = [[Nsrecursivelock alloc] init];        Thread 1    dispatch_async (dispatch_queue_create (NULL, 0), ^{        static void (^testmethod) (int);        TestMethod = ^ (int value)        {            [_lock lock];            if (value > 0)            {                [nsthread sleepfortimeinterval:1];                NSLog (@ "performed once Oh");                TestMethod (value--);            }            NSLog (@ "Whether to execute here");            [_lock unlock];        };                TestMethod (5);    });    

Execution Result:

2017-12-12 11:49:43.378299+0800 nslock[1419:176157] executed once oh 2017-12-12 11:49:44.380543+0800 NSLock[1419:176157] Executed once Oh 2017-12-12 11:49:45.382145+0800 nslock[1419:176157] performed once Oh 2017-12-12 11:49:46.387148+0800 NSLock[1419:176157] Executed once Oh 2017-12-12 11:49:47.388813+0800 nslock[1419:176157] performed once Oh 2017-12-12 11:49:48.389408+0800 NSLock[1419:176157] Executed once Oh 2017-12-12 11:49:49.392983+0800 nslock[1419:176157] performed once Oh 2017-12-12 11:49:50.396521+0800 NSLock[1419:176157] Executed once Oh 2017-12-12 11:49:51.399108+0800 nslock[1419:176157] performed once Oh 2017-12-12 11:49:52.399976+0800 NSLock[1419:176157] Executed once Oh 2017-12-12 11:49:53.404280+0800 nslock[1419:176157] performed once Oh 2017-12-12 11:49:54.409044+0800 NSLock[1419:176157] Executed once Oh 2017-12-12 11:49:55.412670+0800 nslock[1419:176157] performed once Oh 2017-12-12 11:49:56.413754+0800 NSLock[1419:176157] Executed once Oh 2017-12-12 11:49:57.414257+0800 nslock[1419:176157] executed once OH
4. Nsconditionlock Condition Lock

Nsconditionlock more than Nslock a condition parameter, we can be understood as a condition indicator.

@property (readonly) Nsinteger condition; This property is very important, the external incoming condition is the same as to get to the lock object, and vice versa to block the current thread until condition the same-(void) Lockwhencondition: (Nsinteger) condition; Condition is the same as the inside to get the lock object and immediately return, otherwise the blocking thread until condition the same-(BOOL) trylock;//attempt to acquire the lock object, to obtain a successful pairing unlock-(BOOL) Trylockwhencondition: (nsinteger) condition; Ibid.-(void) Unlockwithcondition: (Nsinteger) condition; Unlock, and set lock.condition = condition

Nsconditionlock *clock = [[Nsconditionlock alloc] initwithcondition:0];        Thread 1    dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{        if ([CLock Trylockwhencondition:0]) {            NSLog (@ "Thread 1");            [CLock unlockwithcondition:1];        } else{            NSLog (@ "failed");        }    );        Thread 2    dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{        [CLock Lockwhencondition:3];        NSLog (@ "Thread 2");        [CLock Unlockwithcondition:2];    });        Thread 3    dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{        [CLock Lockwhencondition:1];        NSLog (@ "Thread 3");        [CLock Unlockwithcondition:3];    });

Output Result:

2017-12-12 13:32:24.060013+0800 Conditional lock-nsconditionlock[1783:250080] Thread 12017-12-12 13:32:24.060461+0800 Conditional lock- NSCONDITIONLOCK[1783:250078] Thread 32017-12-12 13:32:24.060626+0800 Conditional lock-nsconditionlock[1783:250079] Thread 2

-When we initialize this lock, given its initial condition is 0;

-Execute Trylockwhencondition: When we pass in the condition indicator is also 0, so thread 1 plus lock succeeded.

-Execute Unlockwithcondition: When the condition will be changed to 0 1

-Because condition is 1, go to Thread 3 first, then thread 3 will change condition to 3,

-finally walked the thread 2

As you can see, Nsconditionlock can also implement dependencies between tasks.

5. Nscondition

Nscondition actually acts as a lock and a thread checker. The lock is mainly to protect the data source when the condition is detected, perform the task that the condition raises, and the thread checker depends on the condition to decide whether to continue, that is, whether the thread is blocked.

Nscondition implements the Nslocking protocol, and when multiple threads access the same piece of code, the wait is the watershed, and one thread waits for the other thread to unlock before it goes through the wait code.

[Condition lock];//is generally used for multi-threaded simultaneous access, modification of the same data source, to ensure that the data source is only accessed, modified at the same time, the command of other threads need to wait outside lock, only to unlock, access to [condition unlock];/ /with lock use [condition wait];//to keep the current thread in the waiting state [condition SIGNAL];//CPU signals to tell the thread not to wait, can continue execution

We can look at the problem of a producer consumer,

The consumer obtains the lock, takes the product, if does not have the product, waits wait, this time will release the lock, knows the thread to wake it to consume the product.

The producer makes the product, first also must obtain the lock, then produces, then sends the signal, this can awaken wait the consumer

#import "ViewController.h" @interface Viewcontroller () @property (Strong, nonatomic) nscondition *condition; @property ( Assign, nonatomic) Nsinteger goodnum; @end @implementation viewcontroller-(void) viewdidload {    [super viewdidload];        _goodnum = 0;        _condition = [[Nscondition alloc] init];        [Nsthread detachnewthreadselector: @selector (buygoods) totarget:self Withobject:nil];        [Nsthread detachnewthreadselector: @selector (shopgoods) totarget:self Withobject:nil];    } -(void) buygoods{    [_condition lock];    while (_goodnum = = 0) {        NSLog (@ "Current sales number is 0, cannot sell, wait");        [_condition wait];    }    _goodnum--;    NSLog (@ "bought one-%ld", _goodnum);    [_condition unlock];} -(void) shopgoods{    [_condition lock];    _goodnum++;    NSLog (@ "Ready to sell one-%ld", _goodnum);    [_condition signal];    NSLog (@ "Tell the buyer to buy it");    [_condition unlock];}

Output Result:

2017-12-12 14:43:48.995787+0800 nscondition[2410:357340] The current number of sales is 0, can not sell, waiting for 2017-12-12 14:43:48.996067+0800 NSCondition [2,410:357,341] ready to sell A-12017-12-12 14:43:48.996578+0800 nscondition[2410:357341] Tell buyers can buy 2017-12-12 14:43:48.997806+ 0800 nscondition[2410:357340] bought a-0

We can see that when consumers want to buy things, because the initial quantity of goods is 0, so can only wait for the producers to produce goods, ready to sell, there are goods, will signal, tell the consumer can buy.

6. Locks implemented using the C language pthread_mutex_t
#import "ViewController.h" #import <pthread.h> @interface Viewcontroller () @end @implementation viewcontroller-( void) Viewdidload {    [super viewdidload];    __block pthread_mutex_t Mutex;        Pthread_mutex_init (&mutex, NULL);        Thread 1    dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{        pthread_mutex_ Lock (&mutex);        NSLog (@ "Thread 1 start Execution");        for (Nsinteger i = 1; i <=; i++) {            sleep (1);            NSLog (@ "Thread 1 is executing----%ld", i);        }        Pthread_mutex_unlock (&mutex);    });    Thread 2    dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_low, 0), ^{        Pthread_mutex_lock ( &mutex);        NSLog (@ "Thread 1 executes, thread 2 starts execution");        Pthread_mutex_unlock (&mutex);    });    

Output Result:

2017-12-12 14:54:16.343540+0800 Pthread_mutex-Mutual exclusion lock [2,518:371,518] Thread 1 starts execution of 2017-12-12 14:54:17.348019+0800 Pthread_mutex-Mutex [2,518:371,518] thread 1 in execution----12017-12-12 14:54:18.348439+0800 Pthread_mutex-Mutex [2,518:371,518] thread 1 executing----22017-12-12 14:54:19.351159+0800 Pthread_mutex-Mutex [2,518:371,518] thread 1 in execution-- --32017-12-12 14:54:20.355283+0800 Pthread_mutex-Mutual exclusion lock [2,518:371,518] thread 1 in execution----42017-12-12 14:54:21.358290+0800 Pthrea D_mutex-Mutex [2,518:371,518] thread 1 executing----52017-12-12 14:54:22.361572+0800 Pthread_mutex-Mutex [2,518:371,518] thread 1 executing----620 17-12-12 14:54:23.362013+0800 Pthread_mutex-Mutual exclusion lock [2,518:371,518] thread 1 in execution----72017-12-12 14:54:24.363130+0800 pthread_ Mutex-mutex [2,518:371,518] thread 1 executing----82017-12-12 14:54:25.366042+0800 Pthread_mutex-Mutex [2,518:371,518] thread 1 executing----92017 -12-12 14:54:26.370250+0800 Pthread_mutex-Mutual exclusion lock [2,518:371,518] thread 1 in execution----102017-12-12 14:54:26.370496+0800 pthread_ Mutex-mutex [2,518:371,519] thread 1 finished, thread 2 starts execution 

 

Common locks in iOS

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.