MST

星途 面试题库

面试题:Objective-C在Mac OS应用性能优化中多线程相关策略

在Objective-C开发的Mac OS应用里,使用多线程来优化性能时,GCD(Grand Central Dispatch)和NSOperationQueue各有什么特点和适用场景?如何利用它们避免资源竞争和死锁问题?请结合实际代码示例阐述。
36.5万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

GCD特点

  1. 简单易用:通过提供dispatch_queue_t队列和一些简单的函数,如dispatch_asyncdispatch_sync,开发者能轻松将任务提交到队列执行,无需像传统线程那样管理线程生命周期。例如:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
    // 这里执行异步任务
    NSLog(@"异步任务在后台线程执行");
});
  1. 基于队列:有主队列、全局队列和自定义队列。主队列与主线程关联,在主线程执行任务;全局队列是系统提供的并行队列。自定义队列可控制任务执行顺序和并发行为。
  2. 自动管理线程:GCD自动管理线程的创建、调度和销毁,开发者只需关注任务逻辑,无需手动管理线程池。

GCD适用场景

  1. 异步任务:网络请求、文件读写等耗时操作。如网络请求:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://example.com"]];
    dispatch_async(dispatch_get_main_queue(), ^{
        // 更新UI
        UIImage *image = [UIImage imageWithData:data];
        self.imageView.image = image;
    });
});
  1. 并行计算:对数组元素进行并行处理等。

NSOperationQueue特点

  1. 面向对象:基于NSOperationNSOperationQueue类,NSOperation是抽象类,常用子类有NSInvocationOperationNSBlockOperation,可将任务封装为对象。例如:
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    // 任务逻辑
    NSLog(@"NSBlockOperation任务执行");
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
  1. 任务依赖管理:可设置任务之间的依赖关系,确保任务按特定顺序执行。如:
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"操作1执行");
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"操作2执行");
}];
[operation2 addDependency:operation1];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation1, operation2] waitUntilFinished:NO];
  1. 可配置性强:能设置最大并发数等属性,控制队列执行行为。

NSOperationQueue适用场景

  1. 复杂任务调度:需要管理任务依赖和执行顺序的场景,如一个任务依赖另一个任务的执行结果。
  2. 灵活控制:需要动态添加、移除操作,或根据运行时情况调整队列属性时。

避免资源竞争和死锁问题

  1. 使用队列同步:在GCD中,使用dispatch_syncdispatch_barrier_async等函数。例如,多个任务读写同一数据时,使用dispatch_barrier_async
dispatch_queue_t queue = dispatch_queue_create("com.example.syncQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
    // 读操作
});
dispatch_barrier_async(queue, ^{
    // 写操作
});
dispatch_async(queue, ^{
    // 读操作
});
  1. 锁机制:使用NSLockNSRecursiveLock等。在NSOperationQueue中:
NSLock *lock = [[NSLock alloc] init];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    [lock lock];
    // 访问共享资源
    [lock unlock];
}];
  1. 避免循环依赖:在设置NSOperation任务依赖时,确保不存在循环依赖,否则会导致死锁。如上述设置依赖示例,合理规划任务顺序避免出现A依赖B,B又依赖A的情况。