OC之并发编程

2018-08-02  本文已影响0人  苏沫离

1、什么是并发编程?

并发编程是指在一台处理器上“同时”处理多个任务。它的目标是充分的利用处理器的每一个核,以达到更高的处理性能。

2、并发处理 与 顺序处理

以顺序方式处理的控制流 以并发方式处理的控制流

并发处理相对于顺序处理的优势:

并发处理意味着同时执行多个任务。但实际上,利用并发机制的程序是否真的并发执行多个任务,取决于运行程序的计算机系统。这里引出了两条概念:并发计算(concurrent computing)与 并行计算(Parallel Computing)。

3、并发计算与 并行计算

从广义上来说:并发计算是软件层面的,与设计相关;并行计算是硬件层面的,与多核CPU相关。

要发挥并发处理的优势,必须以并发编程设计并实现程序,并在能够支持并行处理的硬件运行它。

4、实现并发处理

在了解了并发处理的优势后,我们要学会如何利用它。在计算机系统中,实现并发处理的方式有很多:

5、 CPU 与 GPU

上文提到 CPU 与 GPU ,那么什么是 CPU ?什么是 GPU ?CPU 与 GPU 的区别是什么?

CPU 擅长处理具有复杂计算步骤和复杂数据依赖的计算任务,如分布式计算,数据压缩,人工智能,物理模拟,以及其他很多很多计算任务等。

区别: CUP 和 GPU 之所以大不相同,是由于其设计目的的不同,它们分别针对了两种不同的应用场景:

6、进程 与 线程

进程与进程都是操作系统的基本概念:

进程可能包含多个线程,这些线程可以按顺序执行、以并发方式执行,或者混合使用这两种方式执行。
在 Objective-C 语言中,使用 NSTaskNSThread 管理进程与线程。

6.1、NSTask 创建并管理进程

使用NSTask 可以在 Objective-C 运行时系统中创建并管理进程,NSTask 作为独立进程进行操作,不与其它进程共享内存,包括创建它的进程。一个NSTask 对象只能运行一次,而且其环境需要在它运行以前配置好。

NSTask *task = [[NSTask alloc] init];//使用 init 初始化一个 task
[task setLaunchPath:@"/Users/longlong/Library/Developer/CoreSimulator/Devices/DD8DCEB3-16B7-412A-9F9E-0315A427A638/data/Containers/Bundle/Application/2CDEA0BD-BCB1-40A9-957A-EDE732AE1072/Demo.app/Demo"];//设置启动的程序目录
[task setArguments:@[@"/Users/longlong/Library/Developer/CoreSimulator/Devices/DD8DCEB3-16B7-412A-9F9E-0315A427A638/data/Containers/Bundle/Application/2CDEA0BD-BCB1-40A9-957A-EDE732AE1072/Demo.app/Demo"]];//设置启动需要的参数
[task launch];//启动该进程
NSLog(@"isRunning == %d",[task isRunning]);//使用 isRunning 查询 task 的状态
6.2、NSThread 创建并管理线程

线程是一种操作系统机制,用以并行方式执行多个指令序列。同一个进程中的线程可以共享计算机的内存和其他资源。
使用NSThread 可以创建和控制线程:

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(startChildThread) object:nil];
thread.stackSize = 16;//设置线程占用空间,最小是 16 KB,
thread.name = @"demo.thread2";//设置线程名字
thread.threadPriority = 1.0;//设置线程优先级
[thread start];//开启线程

7、并发处理带来的困难:

虽然并发处理有如此多优点,但要正确实现它并不容易,它主要有以下几个难点:

我们可以使用共享内存消息传递 来处理上述问题。共享内存编程模式会实现共享状态,多个线程都可以访问某些数据。

8、共享内存 与 消息传递

8.1、共享内存

共享内存模式需要一种机制来协调多个线程共用的数据,通常使用同步机制来实现这一目标,如 锁或者判定条件

锁实施是一种互斥策略,避免受保护的数据和资源被多个线程同时访问。使用锁协调对共享数据的访问时,很有可能引发死锁、活锁、资源匮乏等问题,这些问题导致程序中断:

8.2、消息传递

线程能够通过交换消息进行同步和通信,消息传递避免了互斥问题,并与多核、多处理器系统契合。使用消息传递既可以执行同步通信,也可以执行异步通信。在进行同步消息传递时,发送者和接收者会直接连接;消息传递操作完成后,发送者和接收者会断开连接。异步消息传递通过队列传输消息,如图所示:

使用队列传递消息

消息不是在队列之间直接传递,而是通过 消息队列 进行交换。因此,发送者和接收者并不会配对,发送者将消息发给队列后也无需断开连接。使用异步消息传递可以实现并发编程。

框架Foundation 中的NSObject 含有许多方法,这些方法使用消息传递模式,通过线程调用对象的方法。该线程可以是主线程,也可以是分线程

@interface NSObject (NSThreadPerformAdditions)
//waitUntilDone: 参数设置了同步/异步操作
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
    // equivalent to the first method with kCFRunLoopCommonModes

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
    // equivalent to the first method with kCFRunLoopCommonModes
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@end

上述方法,参数 waitUntilDone: 设置了同步YES/异步NO操作。

9、运行循环RunLoop

RunLoop 是一种基于线程的机制,用于调度任务和协调收到的输入事件。如果程序的线程需要回应入栈事件,就必须将之附到运行循环中,以在新事件出现时唤醒该线程。

10、在 Objective-C 中实现并发编程

在Objective-C中实现并发编程有以下几种方式:

参考文章:
并发编程:API 及挑战
iOS 渲染原理解析
iOS离屏渲染的深入研究
协程

上一篇 下一篇

猜你喜欢

热点阅读