面试题答案
一键面试常见导致死锁的场景
- 递归锁与互斥锁混用:在递归锁的临界区内尝试获取互斥锁,而在互斥锁的临界区内又尝试获取递归锁,形成循环依赖。
- 多线程资源竞争:多个线程按照不同顺序获取多个锁。例如线程A先获取锁1,再尝试获取锁2;线程B先获取锁2,再尝试获取锁3;线程C先获取锁3,再尝试获取锁1,此时就会形成死锁。
- 锁的嵌套使用不当:在已经持有一个锁的情况下,在不同层次的代码中再次获取同一个锁,而没有适当的处理,也可能导致死锁。
代码示例
#import <Foundation/Foundation.h>
@interface DeadlockExample : NSObject
@property (nonatomic, strong) NSLock *lock1;
@property (nonatomic, strong) NSLock *lock2;
@end
@implementation DeadlockExample
- (instancetype)init {
self = [super init];
if (self) {
_lock1 = [[NSLock alloc] init];
_lock2 = [[NSLock alloc] init];
}
return self;
}
- (void)thread1Function {
[self.lock1 lock];
NSLog(@"Thread 1 acquired lock1");
sleep(1);
[self.lock2 lock];
NSLog(@"Thread 1 acquired lock2");
[self.lock2 unlock];
[self.lock1 unlock];
}
- (void)thread2Function {
[self.lock2 lock];
NSLog(@"Thread 2 acquired lock2");
sleep(1);
[self.lock1 lock];
NSLog(@"Thread 2 acquired lock1");
[self.lock1 unlock];
[self.lock2 unlock];
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
DeadlockExample *example = [[DeadlockExample alloc] init];
dispatch_queue_t queue1 = dispatch_queue_create("com.example.queue1", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue2 = dispatch_queue_create("com.example.queue2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue1, ^{
[example thread1Function];
});
dispatch_async(queue2, ^{
[example thread2Function];
});
dispatch_main();
}
return 0;
}
在上述代码中,thread1Function
和thread2Function
分别在不同线程中执行,thread1Function
先获取lock1
再获取lock2
,thread2Function
先获取lock2
再获取lock1
,如果两个线程同时执行,就会发生死锁。