面试题答案
一键面试以下是使用NSCondition
实现该线程同步场景的Objective-C代码示例及关键代码解释:
#import <Foundation/Foundation.h>
@interface DataQueue : NSObject
@property (nonatomic, strong) NSMutableArray *queue;
@property (nonatomic, strong) NSCondition *condition;
- (void)produceData:(id)data;
- (NSArray *)consumeData;
@end
@implementation DataQueue
- (instancetype)init {
self = [super init];
if (self) {
_queue = [NSMutableArray array];
_condition = [[NSCondition alloc] init];
}
return self;
}
- (void)produceData:(id)data {
[self.condition lock];
[self.queue addObject:data];
NSLog(@"Produced: %@", data);
[self.condition signal];
[self.condition unlock];
}
- (NSArray *)consumeData {
[self.condition lock];
while (self.queue.count < 3) {
[self.condition wait];
}
NSArray *consumedArray = [self.queue subarrayWithRange:NSMakeRange(0, 3)];
[self.queue removeObjectsInRange:NSMakeRange(0, 3)];
NSLog(@"Consumed: %@", consumedArray);
[self.condition unlock];
return consumedArray;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
DataQueue *dataQueue = [[DataQueue alloc] init];
dispatch_queue_t producerQueue = dispatch_queue_create("com.example.producerQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t consumerQueue = dispatch_queue_create("com.example.consumerQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(producerQueue, ^{
for (int i = 0; i < 10; ++i) {
NSString *data = [NSString stringWithFormat:@"Data %d", i];
[dataQueue produceData:data];
sleep(1);
}
});
dispatch_async(consumerQueue, ^{
while (true) {
NSArray *consumed = [dataQueue consumeData];
if (consumed.count == 0) {
break;
}
sleep(2);
}
});
sleep(15);
}
return 0;
}
关键代码解释
-
初始化部分:
- (instancetype)init { self = [super init]; if (self) { _queue = [NSMutableArray array]; _condition = [[NSCondition alloc] init]; } return self; }
- 初始化
NSMutableArray
用于存储数据,初始化NSCondition
用于线程同步。
- 初始化
-
生产数据方法
produceData:
:- (void)produceData:(id)data { [self.condition lock]; [self.queue addObject:data]; NSLog(@"Produced: %@", data); [self.condition signal]; [self.condition unlock]; }
[self.condition lock];
:锁定NSCondition
,确保对_queue
的操作是线程安全的,避免数据竞争。[self.queue addObject:data];
:将生产的数据添加到队列中。[self.condition signal];
:发送信号,通知等待在NSCondition
上的消费线程队列中有新数据。[self.condition unlock];
:解锁NSCondition
,允许其他线程操作。
-
消费数据方法
consumeData
:- (NSArray *)consumeData { [self.condition lock]; while (self.queue.count < 3) { [self.condition wait]; } NSArray *consumedArray = [self.queue subarrayWithRange:NSMakeRange(0, 3)]; [self.queue removeObjectsInRange:NSMakeRange(0, 3)]; NSLog(@"Consumed: %@", consumedArray); [self.condition unlock]; return consumedArray; }
[self.condition lock];
:锁定NSCondition
,确保对_queue
的操作是线程安全的。while (self.queue.count < 3) { [self.condition wait]; }
:使用while
循环检查队列中的数据是否足够(至少3个),如果不足则调用[self.condition wait];
,使当前线程等待,同时释放NSCondition
的锁,允许其他线程操作队列。当其他线程调用signal
或broadcast
时,此线程被唤醒,重新获取锁并检查条件。这一步避免了死锁,因为线程在等待时会释放锁。NSArray *consumedArray = [self.queue subarrayWithRange:NSMakeRange(0, 3)];
和[self.queue removeObjectsInRange:NSMakeRange(0, 3)];
:从队列中取出并移除前3个数据。[self.condition unlock];
:解锁NSCondition
,允许其他线程操作。return consumedArray;
:返回消费的数据。
-
主函数中的多线程调度:
dispatch_queue_t producerQueue = dispatch_queue_create("com.example.producerQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_queue_t consumerQueue = dispatch_queue_create("com.example.consumerQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(producerQueue, ^{ for (int i = 0; i < 10; ++i) { NSString *data = [NSString stringWithFormat:@"Data %d", i]; [dataQueue produceData:data]; sleep(1); } }); dispatch_async(consumerQueue, ^{ while (true) { NSArray *consumed = [dataQueue consumeData]; if (consumed.count == 0) { break; } sleep(2); } });
- 创建生产者和消费者队列,并在队列中异步执行生产和消费任务。生产者循环生产10个数据,消费者持续消费数据,直到没有足够数据可消费。
sleep
函数用于模拟实际的生产和消费延迟。
- 创建生产者和消费者队列,并在队列中异步执行生产和消费任务。生产者循环生产10个数据,消费者持续消费数据,直到没有足够数据可消费。
通过上述实现,利用NSCondition
实现了线程同步,避免了数据竞争和死锁,满足了题目要求的复杂线程同步场景。