IOS-multi-threaded applications and ios multi-threaded applications
I. Share resources
Shared resources: a resource in the memory is simultaneously accessed by multiple processes, and each process may modify the data of this resource.
Problem: If thread A accesses A resource C and modifies the data in it, thread B also accesses resource C and modifies the data in C; after thread A and thread B are executed, the data in resource C is not initially set.
At this time, if the user wants to obtain the data of resource C modified by thread A, but the data of resource C is also modified by thread B, the error data is obtained; if the user wants to obtain the data of resource C modified by thread B, but the data of resource C is also modified by thread A, the error data is obtained.
The following code shows how to sell a train ticket.
Train ticket Data Model
1 // LHTicketModal. h 2 # import <Foundation/Foundation. h> 3 4 @ interface LHTicketModal: NSObject 5 6 @ property (nonatomic) NSUInteger ticketCount; // number of remaining votes 7 @ property (nonatomic) NSUInteger ticketSaleCount; // sell quantity 8 9 @ end10 11 // LHTicketModal. m12 # import "LHTicketModal. h "13 14 static const NSUInteger kTicketTotalCount = 50; 15 16 @ implementation LHTicketModal17 18-(instancetype) init {19 20 self = [super init]; 21 22 if (self) {23 24 // the remaining number of votes for initialization should be 25 _ ticketCount = kTicketTotalCount; 26 27 // The number of initial sales votes should be 028 _ ticketSaleCount = 0; 29 30} 31 32 return self; 33 34} 35 36 @ end
UIViewController code
1 // LHSharedViewController. h 2 # import "LHSharedViewController. h "3 # import" LHTicketModal. h "4 5 @ interface LHSharedViewController () 6 7 // ticket Model 8 @ property (nonatomic, strong) LHTicketModal * ticket; 9 10 // thread object 11 @ property (nonatomic, strong) NSThread * threadBJ; 12 @ property (nonatomic, strong) NSThread * threadSH; 13 14 @ end15 16 // LHSharedViewController. m17 @ implementation LHSharedViewController18 19-(void) viewDidLoad {20 21 [super viewDidLoad]; 22 23 // 1. initialize the ticket model object 24 _ ticket = [[LHTicketModal alloc] init]; 25 26 // 2. initialize the thread object and set the thread name 27 _ threadBJ = [[NSThread alloc] initWithTarget: self selector: @ selector (sellTickets :) object: @ "Beijing sell"]; 28 29 _ threadBJ. name = @ "Beijing"; 30 31 _ threadSH = [[NSThread alloc] initWithTarget: self selector: @ selector (sellTickets :) object: @ ""]; 32 33 _ threadSH. name = @ "Shanghai"; 34 35} 36 37 // method of thread execution 38-(void) sellTickets :( NSString *) str {39 40 while (YES) {41 42 // determine whether the remaining amount is greater than 0. if it is greater than 0, 43 if (_ ticket. ticketCount> 0) {44 45 // pause for a period of time 46 [NSThread sleepForTimeInterval: 0.2]; 47 48 // sell a ticket. The remaining number of votes is reduced by 1, and the number of votes sold is increased by 149 _ ticket. ticketCount --; 50 51 _ ticket. ticketSaleCount ++; 52 53 // get the current process 54 NSThread * currentThread = [NSThread currentThread]; 55 56 NSLog (@ "% @ sold a ticket, % lu tickets left ", currentThread. name, _ ticket. ticketCount); 57 58} 59 60} 61 62} 63 64 // button Action Method 65-(IBAction) startSaleBtnClick :( id) sender {66 67 // enable thread 68 [_ threadBJ start]; 69 70 [_ threadSH start]; 71 72 73}
Click the button and the thread starts running.
It can be seen that shared resources are accessed and modified by multiple threads at the same time, resulting in incorrect data.
Then the solution to this situation is to lock
A lock is used to lock a piece of code. After the lock, if a thread is modifying the data of the shared resource, no other threads will access the resource to modify it, other processes can modify the resource code until the current thread has finished modifying the resource code.
We can regard shared resources as a room and threads as human beings. When a person enters the room, the door will be locked (locked), and various room arrangements will be made. At this time, other people will not be able to enter the room, because there is no key; until the current person leaves the room, other people can enter the room for arrangement.
There are multiple lock methods. Here we will introduce two methods.
Method 1: Use the @ synchronized (Lock Object) {} keyword
You only need to modify the sellTickets method of the above Code, and the rest will not change. Here, change the method name to sellTickets_v2.
1-(void) sellTickets_v2 :( NSString *) str {2 3 while (YES) {4 5 // lock the current object 6 @ synchronized (self) {7 8 // determine whether the remaining amount is greater than 0. if it is greater than 0, 9 if (_ ticket. ticketCount> 0) {10 11 // pause for a period of time 12 [NSThread sleepForTimeInterval: 0.2]; 13 14 // sell a ticket. The remaining number of votes is reduced by 1, and the number of votes sold is increased by 115 _ ticket. ticketCount --; 16 17 _ ticket. ticketSaleCount ++; 18 19 // get the current process 20 NSThread * currentThread = [NSThread currentThread]; 21 22 NSLog (@ "% @ sold a ticket, % lu tickets left ", currentThread. name, _ ticket. ticketCount); 23 24} 25 26} 27 28} 29 30}
Run the program again and click the button. Result
Method 2: Use NSCondition class
Declare in class extension and initialize in viewDidLoad Method
1-(void) sellTickets_v3 :( NSString *) str {2 3 while (YES) {4 5 // use NSCondition to lock 6 [_ ticketCondition lock]; 7 8 // determine whether the remaining amount is greater than 0. if the remaining amount is greater than 0, 9 if (_ ticket. ticketCount> 0) {10 11 // pause for a period of time 12 [NSThread sleepForTimeInterval: 0.2]; 13 14 // sell a ticket. The remaining number of votes is reduced by 1, and the number of votes sold is increased by 115 _ ticket. ticketCount --; 16 17 _ ticket. ticketSaleCount ++; 18 19 // get the current process 20 NSThread * currentThread = [NSThread currentThread]; 21 22 NSLog (@ "% @ sold a ticket, % lu tickets left ", currentThread. name, _ ticket. ticketCount); 23 24} 25 26 // use NSCondition to unlock 27 [_ ticketCondition unlock]; 28 29} 30 31}
The running result is the same as above.
When NSCondition is used, lock code is placed in the middle of loac and unlock
Summary:
1. Advantages and Disadvantages of mutex lock
Advantage: effectively prevents data security problems caused by multi-thread resource snatch
Disadvantage: it consumes a lot of CPU resources.
2. Prerequisites for mutex lock
Multiple Threads snatch the same resource
Thread Synchronization. mutex lock is used for thread synchronization.