• IOS multithreading, spin locks and mutex details
  • NSThread for iOS multithreading
  • NSOperation for iOS multithreading
  • IOS Multithreading GCD

preface

NSThread is apple’s official object-oriented thread operation technology. It is simple and convenient. You can directly operate thread objects, but you need to control the life cycle of the thread. [NSThread currentThread] [NSThread currentThread]

1 NSThread briefly

Apple Official Documents

  • aNSThreadThe object represents a thread
  • NSThreadThe function is automatically recalled after executing the task

2 NSThread create

  • Dynamically create
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(threadFunction1: object:@" initialize: thread"]; NSThread = [[NSThread alloc] initWithBlock:^{NSLog(@" init: thread2");}]; NSThread *thread3 = [[NSThread alloc] init];Copy the code

Thread1, thread2, thread3 need to be started by calling start

  • The static create
// Since the static method does not return a value, if you want to get the newly created thread, you need to call the method that gets the current thread in the selector [NSThread detachNewThreadSelector:@selector(threadFunction2:) ToTarget :self withObject:@" static create "];Copy the code

3 NSThread method

  • Start and Cancel
// thread start [thread1 start]; // Thread cancels [thread cancel];Copy the code
  • Thread to stop

The thread stop method immediately terminates all threads except the main thread (whether or not they are executing a task) and exits. This method needs to be invoked while controlling the state of all threads, otherwise it may cause memory problems and cannot be restarted once stopped

[NSThread exit];
Copy the code
  • Thread method
// is the main thread [NSThread isMainThread]; // set the mainThread to [NSThread mainThread]; // get the currentThread [NSThread currentThread]; / / set the thread priority [NSThread currentThread]. QualityOfService = NSQualityOfServiceBackground; // Thread pause [NSThread sleepForTimeInterval:1.0]; [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]].Copy the code

4 Communication methods between threads

  • Specifies the current thread of execution
[self performSelector:@selector(threadFunction)]; [self performSelector:@selector(threadFunction) withObject:nil]; [the self performSelector: @ the selector (threadFunction) withObject: nil afterDelay: 2.0];Copy the code
  • Other threads specify the main thread to execute
[self performSelectorOnMainThread:@selector(threadFunction) withObject:nil waitUntilDone:YES];

Copy the code
  • Specify other threads in the main thread to perform operations
// this is specified for a thread [self performSelector:@selector(threadFunction) onThread:newThread withObject:nil waitUntilDone:YES]; / / here is specified as a background thread [self performSelectorInBackground: @ the selector (threadFunction) withObject: nil];Copy the code
  • Thread synchronization

Threads may share some resources with other threads, which may cause conflicts when multiple threads read and write the same shared resource. Thread synchronization means that only one thread is allowed to access a resource at a certain time

IOS thread locking is implemented in two ways: NSLock and @synchronized

Advantages: It effectively prevents data security problems caused by multi-threaded resource grabs. Disadvantages: It consumes a large amount of CPU resources

5. Use of NSThread: simulate ticket selling

Scenario: tickets of A cinema are on sale, and Windows are opened in window A and window B for sales. The following is the code implementation

{ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(threadExit) name:NSThreadWillExitNotification object:nil]; Self. ticketsCount = 20; NSThread *windowA = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil]; Windowa. name = @" windowa. name "; [windowA start]; NSThread *windowB = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil]; Windowb. name = @" windowB "; [windowB start]; } // saleTicket - (void)saleTicket {// If the thread starts, saleTicket will be executed. While (1) {// Add the mutex if (self.ticketsCount > 0) {self.ticketsCount--; NSLog(@"%@, %ld", [NSThread currentThread].name, (long)self.ticketsCount); [NSThread sleepForTimeInterval: 0.2]; } else { break; }} - (void)threadExit {NSLog(@" threadExit "); }Copy the code

Execution Result:

Window A, 12 window A, 11 window B, 10 window B, 8 window A, 8 window B, 7 window A, 6 window B, 5 window A, 4 window B, 3 window A, 2 window B, 0 Window A, 1Copy the code

In the process of ticket selling, multiple threads access the same resource, resulting in quantity disorder. In the process of ticket selling, we add mutex to the ticket. Only one thread can operate on the number of tickets at a time, and when the operation is complete, other threads can continue to operate on the number of tickets.

@synchronized(self)Add a mutex
- (void)saleTicket {// After the thread starts, saleTicket is executed, and then the thread exits. While (1) {synchronized(self) {if (self.ticketsCount > 0) {self.ticketscount --; NSLog(@"%@, %ld", [NSThread currentThread].name, (long)self.ticketsCount); [NSThread sleepForTimeInterval: 0.2]; } else { break; }}} // the thread exits.Copy the code

Print result:

Window B, 6 window B, 5 window A, 4 window A, 2 window B, 3 window B, 1 window A, 1 window B, 0Copy the code
Set the thread to always run, custom cancel
{ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(threadExit) name:NSThreadWillExitNotification object:nil]; Self. ticketsCount = 20; NSThread *windowA = [[NSThread alloc] initWithTarget:self selector:@selector(threadWindowA) object:nil]; Windowa. name = @" windowa. name "; [windowA start]; NSThread *windowB = [[NSThread alloc] initWithTarget:self selector:@selector(threadWindowB) object:nil]; Windowb. name = @" windowB "; [windowB start]; [self performSelector:@selector(saleTicket) onThread:windowA withObject:nil waitUntilDone:NO]; [self performSelector:@selector(saleTicket) onThread:windowB withObject:nil waitUntilDone:NO]; } - (void)threadWindowA { NSRunLoop *runLoop1 = [NSRunLoop currentRunLoop]; // Run [runLoop1 runUntilDate:[NSDate date]]; } - (void)threadWindowB { NSRunLoop *runLoop2 = [NSRunLoop currentRunLoop]; / / custom runtime [runLoop2 runMode: NSDefaultRunLoopMode beforeDate: [NSDate dateWithTimeIntervalSinceNow: 12.0]]. } // saleTicket - (void)saleTicket {// If the thread starts, saleTicket will be executed. While (1) {// Add the mutex if (self.ticketsCount > 0) {self.ticketsCount--; NSLog(@"%@, %ld", [NSThread currentThread].name, (long)self.ticketsCount); [NSThread sleepForTimeInterval: 0.2]; } else {if ([NSThread currentThread]. IsCancelled) {break; } else {NSLog(@" sold out "); [NSThread currentThread] cancel]; [NSThread currentThread] cancel]; // Stop the current thread runLoop CFRunLoopStop(CFRunLoopGetCurrent()); }}}} - (void)threadExit {NSLog(@" threadExit :%@", [NSThread currentThread].name); }Copy the code

See GitHub-> Multithreading for the full code


If there are shortcomings, welcome to correct, if you feel good writing, remember to give a thumbs up!