MST
星途 面试题库

面试题:Objective-C多任务处理中的资源竞争问题及解决方案

在Objective-C的多任务处理场景下,不同任务可能会竞争共享资源。请举例说明一种可能出现资源竞争的场景,比如多个后台任务同时访问并修改同一个数据库记录。详细阐述你会采取哪些措施来避免资源竞争,确保数据的一致性和程序的稳定性,例如使用锁机制或其他并发控制技术,并说明每种方案的优缺点。
34.5万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

资源竞争场景举例

以多个后台任务同时访问并修改同一个数据库记录为例,比如在一个电商应用中,有两个后台任务,任务A负责处理用户下单时减少商品库存,任务B负责处理商品补货操作增加库存。假设当前商品库存为100,任务A读取库存为100后,还未进行库存减少操作时,任务B也读取库存为100,然后任务A减少库存变为99,任务B增加库存变为101,而不是正确的102,这就出现了资源竞争导致数据不一致。

避免资源竞争的措施

1. 锁机制

  • 互斥锁(Mutex)
    • 使用方法:在Objective-C中,可以使用NSLock类。例如:
NSLock *lock = [[NSLock alloc] init];
// 进入临界区
[lock lock];
// 访问和修改数据库记录的代码
[lock unlock];
// 离开临界区
- **优点**:实现简单,能有效防止多个线程同时进入临界区,保证数据一致性。
- **缺点**:如果一个线程在持有锁时发生阻塞,其他线程将一直等待,可能导致性能问题。而且如果使用不当,容易产生死锁,比如多个线程互相等待对方释放锁。
  • 读写锁(Read - Write Lock)
    • 使用方法:可以使用pthread_rwlock(在Objective - C中可以封装使用)。读操作时:
pthread_rwlock_rdlock(&rwlock);
// 执行读数据库记录操作
pthread_rwlock_unlock(&rwlock);

写操作时:

pthread_rwlock_wrlock(&rwlock);
// 执行写数据库记录操作
pthread_rwlock_unlock(&rwlock);
- **优点**:允许多个线程同时进行读操作,提高了读性能,适用于读多写少的场景。写操作时会独占锁,保证数据一致性。
- **缺点**:实现相对复杂。如果写操作频繁,读操作可能会长时间等待,降低整体性能。同样存在死锁风险。

2. 队列调度

  • GCD(Grand Central Dispatch)
    • 使用方法:利用串行队列,将所有对数据库的操作都放到同一个串行队列中执行。例如:
dispatch_queue_t serialQueue = dispatch_queue_create("com.example.databaseQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
    // 访问和修改数据库记录的代码
});
- **优点**:基于队列的方式,简单易用,不需要手动管理锁,避免了死锁问题。并且GCD会自动管理线程,提高了系统资源利用率。
- **缺点**:由于是串行执行,在高并发场景下,可能会导致任务积压,影响性能。
  • NSOperationQueue
    • 使用方法:创建一个NSOperationQueue,并设置其最大并发数为1,然后将所有与数据库操作相关的NSOperation添加到该队列中。例如:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    // 访问和修改数据库记录的代码
}];
[queue addOperation:operation];
- **优点**:面向对象的方式,易于理解和维护。通过设置最大并发数,可以灵活控制并发度,一定程度上避免资源竞争。
- **缺点**:相比GCD,使用起来稍显复杂。同样在高并发场景下,可能因并发度限制导致任务执行效率降低。

3. 信号量(Semaphore)

  • 使用方法:在Objective - C中,可以使用dispatch_semaphore。例如:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 访问和修改数据库记录的代码
dispatch_semaphore_signal(semaphore);
- **优点**:可以控制同时访问资源的线程数量,比互斥锁更灵活。例如可以允许一定数量的线程同时读数据库。
- **缺点**:如果信号量的值设置不当,可能达不到预期的并发控制效果,而且同样可能出现死锁问题。