自旋锁 & 互斥锁
自旋锁:
atomic、OSSpinLock、dispatch_semaphore_t
临界区加锁,不解锁一直忙碌不停循环,没有线程切换的时间开销,用于执行频繁访问临界区任务。Runtime引用计数大量使用自旋锁。
互斥锁:
pthread_mutex、 @synchronized、NSLock、NSCondition、NSConditionLock、NSRecursiveLock
临界区加锁,被阻塞线程进入休眠,直到互斥锁释放后才被唤醒,线程开销大,用于不经常切换切耗时的操作。
线程通信
performSelector
NSMachPort
GCD
GCD & NSOperation
GCD:
- 基于C语言的面向内核多线程的技术,用于代替NSthread,发挥CPU多核优势提高CPU效率。
- 最基本的是dispatchQueue,FIFO队列,
- 并行Concurrent Queues、串行Serial Queues,同步线程sync、异步线程async
- 使用简洁,不用考虑底层实现,
- 很难控制并发异步线程之间的执行顺序和依赖关系
- 无法终止已经执行的线程
NSOperation
- 面向对象的多线程技术,是基于GCD的封装,GCD的高级抽象,
- 配合NSOperationQueue配合使用,
- 不支持FIFO对列
- 可以设置线程间优先级和依赖关系,
- 设置最大并发数,
- 可以取消未执行线程,但不能终止正在执行线程
-可以通过KVO观察NSOperation的状态
NSOperation
使用NSOperation子类的方式有三种:
NSInvocationOperation
NSBlockOperation
自定义子类继承NSOperation,实现内部相应的方法
NSOperation其实就是对GCD的一个封装。
创建NSInvocationOperation对象
-(id)initWithTarget:(id) target selector:(SEL)sel object:(id) arg;
调用start方法开始执行操作
-(void)start;
一旦执行操作,就会调用target的sel方法。
注意:默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作。
只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作
创建NSBlockOperation对象
+(id)blockOperationWithBlock:(void (^)(void)) block;
通过addExecutionBlock:方法添加更多的操作
-(void)addExecutionBlock:(void (^)(void)) block;
注意:只要NSBlockOperation封装的操作数>1, 就会异步执行操作。
1 - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
2 {
3 // [self opDemo1];
4 // [self opDemo2];
5 // [self opDemo3];
6 [self opDemo4];
7 }
8
9 - (void)down
10 {
11 for (int i = 0; i < 2; i ++) {
12 NSLog(@"%d", i+2);
13 }
14 }
15
16 #pragma mark - 单个NSInvocationOperation使用
17 - (void) opDemo1
18 {
19 NSLog(@"1");
20 //创建操作
21 NSOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(down) object:@"Invocation"];
22 //直接在当前线程执行(同步执行)【没有开辟线程】
23 [op start];
24 //放到队列gg
25 // NSOperationQueue * que = [[NSOperationQueue alloc] init];
26 // //只要把操作添加到队列,就会异步执行任务(但是任务中的任务会顺序执行)【开辟了线程】
27 // [que addOperation:op];
28 NSLog(@"3");
29 }
30
31 - (void) opDemo2
32 {
33 NSLog(@"1");
34 /**
35 1.队列(GCD里面的并发(全局)队列使用最多),所以NSOperation技术直接把GCD里面的并发技术封装起来
36 2.NSOperationQueue,本质就是GCD里面的并发队列
37 3.操作是GCD里面的异步执行的任务
38 **/
39 NSOperationQueue * q = [[NSOperationQueue alloc] init];
40 for (int i = 0; i < 2; i ++) {
41 NSOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(down) object:@"Invocation"];
42 [q addOperation:op];
43 }
44 NSLog(@"4");
45 }
46
47 - (void) opDemo3
48 {
49 NSLog(@"1");
50 //相当于GCD主队列
51 NSOperationQueue * q = [NSOperationQueue mainQueue];
52 //当NSOpertaion获取主线程,不会在开辟线程,但是里面的任务会在其他主线程任务执行完成后才回归执行
53 for (int i = 0; i < 5; i ++) {
54
55 NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{
56 NSLog(@"%@==========%d", [NSThread currentThread], i);
57 }];
58 //将block放入到队列
59 //block中可以添加多个任务
60 [q addOperation:op];
61 }
62 NSLog(@"6");
63
64 }
65 66 - (void) opDemo4
67 {
68 NSLog(@"1");
69 NSOperationQueue * q = [[NSOperationQueue alloc] init];
70 //block块中可以写多个任务(里面串行队列),相当于GCD中的并行串行队列
71 NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{
72 NSLog(@"2");
73 NSLog(@"3");
74 NSLog(@"4");
75 }];
76 [q addOperation:op];
77 //还可以在外面给队列添加任务.但是遵循fifo
78 [op addExecutionBlock:^{
79 NSLog(@"6");
80 NSLog(@"7");
81 }];
82 NSLog(@"5");
83 }