MST

星途 面试题库

面试题:Objective-C中GCD在复杂异步任务依赖场景下的优化

假设在一个Objective-C项目中,有一系列复杂的异步任务,任务A完成后,同时触发任务B和任务C,任务B和任务C完成后才能执行任务D,且任务执行过程中可能涉及到数据的共享与竞争。请使用GCD设计一个高效且线程安全的解决方案,并阐述如何通过GCD的特性(如信号量、组等)来优化性能和确保数据一致性。
12.2万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. 使用GCD实现任务调度

#import <Foundation/Foundation.h>

// 假设这些是任务函数
void taskA() {
    NSLog(@"Task A started");
    // 模拟异步任务
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Task A completed");
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            taskB();
        });
        
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            taskC();
        });
        
        dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            taskD();
        });
    });
}

void taskB() {
    NSLog(@"Task B started");
    // 模拟异步任务
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Task B completed");
    });
}

void taskC() {
    NSLog(@"Task C started");
    // 模拟异步任务
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Task C completed");
    });
}

void taskD() {
    NSLog(@"Task D started");
    // 模拟异步任务
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Task D completed");
    });
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        taskA();
        // 防止主线程退出
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    }
    return 0;
}

2. GCD特性优化性能与确保数据一致性

  • 信号量(Semaphore)
    • 作用:信号量可以用于控制对共享资源的访问数量。在上述代码中,dispatch_semaphore_create(0) 创建了一个初始值为0的信号量,dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) 使得主线程等待,直到信号量的值变为大于0,从而防止主线程在异步任务完成前退出。
    • 数据一致性:当多个任务需要访问共享数据时,可以使用信号量来保证同一时间只有一个任务能访问共享数据。例如,在任务B和任务C中,如果都要访问某个共享变量 sharedVariable,可以这样做:
dispatch_semaphore_t dataSemaphore = dispatch_semaphore_create(1);
// 在任务B中访问共享变量
dispatch_semaphore_wait(dataSemaphore, DISPATCH_TIME_FOREVER);
sharedVariable = someNewValue;
dispatch_semaphore_signal(dataSemaphore);
// 在任务C中访问共享变量
dispatch_semaphore_wait(dataSemaphore, DISPATCH_TIME_FOREVER);
NSLog(@"Shared variable value: %d", sharedVariable);
dispatch_semaphore_signal(dataSemaphore);
  • 组(Dispatch Group)
    • 作用dispatch_group_create 创建一个任务组,dispatch_group_async 将任务添加到组中,dispatch_group_notify 可以在组内所有任务完成后执行指定的任务。在代码中,group 用于管理任务B和任务C,确保它们都完成后再执行任务D,优化了性能,避免任务D在任务B或C未完成时就开始执行。
    • 数据一致性:通过组的机制,可以保证在共享数据相关的任务都完成后,再进行依赖这些共享数据的后续操作。例如,任务B和任务C都对共享数据进行修改,任务D依赖这些修改后的数据,通过组就可以确保任务D在任务B和C对数据修改完成后才执行,保证数据一致性。