C++ 线程(串行 并行 同步 异步)详解
看了很多关于这类的文章,一直没有总结。不总结的话就会一直糊里糊涂,以下描述都是自己理解的非官方语言,不一定严谨,可当作参考。
首先,进程可理解成一个可执行文件的执行过程。在ios app上的话我们可以理解为我们的app的.ipa文件执行过程也即app运行过程。杀掉app进程就杀掉了这个app在系统里运行所占的内存。
线程:线程是进程的最小单位。一个进程里至少有一个主线程。就是那个main thread。非常简单的app可能只需要一个主线程即UI线程。当然大部分还是会有一些子线程的,比如如果你用了AFNetWorking,你的请求都是开辟了子线程。
关于串行,并行,同步,异步,我还是以下面代码的方式做个说明。
首先button点击事件运行在主线程里,先是在主线程里做了打印了一句话,然后创建了一个串行或者并行的队列,之后连续创建了3个同步或者异步的block任务放入此队列中,最后再在主线程里打印一句话。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
- (IBAction)serialSync:(id)sender { NSLog(@ "start log in main thread" ]); dispatch_queue_t myQueue = dispatch_queue_create( "myQueue" , NULL); for (NSInteger n = 0; n < 3; n++) { dispatch_sync(myQueue, ^{ for (NSInteger i = 0; i < 500000000; i++) { if (i == 0) { NSLog(@ "串行同步任务%ld -> 开始%@" ,n,[NSThread currentThread]); } if (i == 499999999) { NSLog(@ "串行同步任务%ld -> 完成" ,( long )n); } } }); } NSLog(@ "阻塞我没有?当前线程%@" ,[NSThread currentThread]); } - (IBAction)serialAsync:(id)sender { NSLog(@ "start log in main thread" ]); dispatch_queue_t myQueue = dispatch_queue_create( "myQueue" , NULL); //创建一个串行队列 for (NSInteger n = 0; n < 3; n++) { dispatch_async(myQueue, ^{ for (NSInteger i = 0; i < 500000000; i++) { if (i == 0) { NSLog(@ "串行异步任务%ld -> 开始%@" ,n,[NSThread currentThread]); } if (i == 499999999) { NSLog(@ "串行异步任务%ld -> 完成" ,( long )n); } } }); } NSLog(@ "阻塞我没有?当前线程%@" ,[NSThread currentThread]); } - (IBAction)concurrentSync:(id)sender { NSLog(@ "start log in main thread" ]); dispatch_queue_t myQueue = dispatch_queue_create( "myQueue" , DISPATCH_QUEUE_CONCURRENT); for (NSInteger n = 0; n < 3; n++) { dispatch_sync(myQueue, ^{ for (NSInteger i = 0; i < 500000000; i++) { if (i == 0) { NSLog(@ "并行同步任务%ld -> 开始%@" ,( long )n,[NSThread currentThread]); } if (i == 499999999) { NSLog(@ "并行同步任务%ld -> 完成" ,( long )n); } } }); } NSLog(@ "阻塞我没有?当前线程%@" ,[NSThread currentThread]); } - (IBAction)concurrentAsync:(id)sender { NSLog(@ "start log in main thread" ]); dispatch_queue_t myQueue = dispatch_queue_create( "myQueue" , DISPATCH_QUEUE_CONCURRENT); for (NSInteger n = 0; n < 3; n++) { dispatch_async(myQueue, ^{ for (NSInteger i = 0; i < 500000000; i++) { if (i == 0) { NSLog(@ "并行异步任务%ld -> 开始%@" ,n,[NSThread currentThread]); } if (i == 499999999) { NSLog(@ "并行异步任务%ld -> 完成" ,( long )n); } } }); } NSLog(@ "阻塞我没有?当前线程%@" ,[NSThread currentThread]); } |
最后的结果如图:
其中我把第一句打印和最后一句打印用玫红色表示,它们都运行在当前线程。
方框表示队列,3个block任务分别为3种不同的颜色。
可以看出:
串行即上一个block任务执行完毕下一个任务才加入到队列中。
并行即其中的任务同时加入到队列中。
从运行结果来看
第一个图只有一个主线程:
3个block都是同步即都阻塞当前线程,所以最后那句打印的任务就在3个block运行完之后。
3个block又是串行,所以一个一个运行
第二个图有2个线程即一个主线程一个子线程:
3个block都是异步,没有任务阻塞当前线程。所以最后那句打印是在第一句打印后就可以开始执行的。
3个block都是异步,异步会创建新的线程即至少有一个子线程。
3个block是串行,只有一个任务做完才会加另一个任务入队列,所以只需一个子线程。
第三个图只有一个主线程:
3个block都是同步即都阻塞当前线程,所以最后那句打印的任务就在3个block运行完之后。
3个block是并行,同时被加入队列中。
3个block都是同步,由于同步意味着等待,所以任务的执行表现为顺序执行,其实是一起加进去的但是等待的,跟串行的区别是串行是别的任务做完才把它加进队列中。
第四个图有多个线程:
3个block都是异步,没有任务阻塞当前线程。所以最后那句打印是在第一句打印后就可以开始执行的。
3个block都是异步,异步会创建新的线程即至少有一个子线程。
3个block是并行,需创建多个子线程才能保证任务同时执行。
再看一张图:其中第一个异步为玫红色,两个同步分别以紫色黄色表示,两个异步分别以绿色棕色表示,队列后面的当前线程动作为橘色。虚线代表等待。上面代表串行,下面是并行。
由此图可以看出:
同步block会阻塞当前线程,即会在当前线程中运行。(这里的当前线程为主线程所以会看到UI卡住)
异步block会开辟新的线程。
在串行队列中,异步block任务用的是同一个子线程,因为需要等待任务一个一个地执行,不需要多个线程。
在并行队列中,异步block任务同时执行,系统为其分配线程。图中的例子因第一个异步操作在第二个开始前已经结束了,所以并不是多少个异步操作就创建多少线程,主要还是看需要。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!