Q. iOS開發(fā)中有多少類型的線程麸粮?分別對比
- Pthreads // 跨系統(tǒng)c語言多線程框架,不推薦镜廉。
- NSTread // 面向?qū)ο笈澹枰謩?dòng)管理生命周期
- GCD :Grand Central Dispatch // 主打任務(wù)與隊(duì)列,告訴他要做什么即可娇唯。
- NSOperation & NSOperationQueue // GCD 的封裝齐遵,面向?qū)ο蟆?/li>
Q.GCD和NSOperationQueue對比
GCD是面向底層的C語言API,NSOperationQueue用GCD構(gòu)建封裝的塔插,是GCD的高級抽血梗摇。
- GCD執(zhí)行效率更高,而且由于隊(duì)列中執(zhí)行的是由block構(gòu)成的任務(wù)想许,這是一個(gè)輕量級別的數(shù)據(jù)結(jié)構(gòu)伶授,寫起來更方便。
- GCD只支持FIFO的隊(duì)列流纹,而NSOperationQueue可以用過設(shè)置最大并發(fā)數(shù)糜烹,設(shè)置優(yōu)先級,添加依賴關(guān)系等調(diào)整執(zhí)行順序漱凝。
- NSOperationQueue甚至可以跨隊(duì)列設(shè)置依賴關(guān)系疮蹦,但是GCD只能通過設(shè)置串行隊(duì)列,或者在隊(duì)列內(nèi)添加barrier(dispatch_barrier_async)任務(wù)茸炒,才能控制執(zhí)行順序愕乎,較為復(fù)雜。
- NSOperationQueue因?yàn)槊嫦驅(qū)ο蟊诠灾С諯VO妆毕,可以監(jiān)測operation是否在執(zhí)行(isExecuted)、是否結(jié)束(isFinished)贮尖、是否取消(isCanceld)
Q.如何實(shí)現(xiàn)同步笛粘,有多少說多少
- Disaptch_async (在同一個(gè)串行隊(duì)列)
- Dispatch_sync()
- Dispatch_barrier_sync()
- Dispatch_group_create() + dispatch_group_wait()
- Dispatch_apply(1,...)
- NSOperationQueue.maxConcurrentOperationCount = 1
- os_unfair_lock
- Pthread_mutex 互斥鎖
- @synchronied
- NSLock
- NSRecursiveLock 遞歸鎖
- NSConditionLock & NSCondition 條件鎖
- Dispatch_semaphore_create() + dispatch_semaphore_wait()
Q.dispath_once實(shí)現(xiàn)原理
1.讀取token值 dispatch_once_t.dgo_once
2.若Block已完成,return
3.若block沒有完成,嘗試原子性修改dispatch_once_t.dgo_once 值為 DLOCK_ONCE_UNLOCKED
4.修改成功薪前,執(zhí)行block润努,原子性修改 dispatch_once_t.dgo_once 為 DLOCK_ONCE_DONE
5.若失敗,則進(jìn)入循環(huán)等待示括。
Q.什么情況下會(huì)死鎖
-
單線程
對正在執(zhí)行任務(wù)的串行隊(duì)列添加同步任務(wù)
/// 在主線程中執(zhí)行這句代碼 dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"這里死鎖了"); }); /// 在哪里執(zhí)行都可以 dispatch_queue_t theSerialQueue = dispatch_queue_create("我是個(gè)串行隊(duì)列", DISPATCH_QUEUE_SERIAL); dispatch_async(theSerialQueue, ^{ /// 正在執(zhí)行任務(wù)铺浇,同步異步無所謂 NSLog(@"第一層"); /// 同一個(gè)串行隊(duì)列 dispatch_sync(theSerialQueue, ^{ NSLog(@"第二層"); }); });
- 多線程
簡單來說,A等B垛膝,同時(shí)B等A鳍侣。
例如某個(gè)任務(wù)需要多個(gè)資源,比如資源1吼拥、資源2倚聚。此時(shí),線程A和線程B都要執(zhí)行這個(gè)任務(wù)凿可。但是惑折,線程A先搶占了資源1,同時(shí)線程B搶占了資源2枯跑。這個(gè)時(shí)候惨驶,線程A還需要資源2才能執(zhí)行任務(wù);同樣的敛助,線程B需要資源1才能執(zhí)行任務(wù)粗卜。于是,A等B纳击,B等A休建,死鎖來了。
- (void)deadLock {
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(deadLock1) object:nil];
[thread1 setName:@"【線程 湯姆】"];
NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(deadLock2) object:nil];
[thread2 setName:@"【線程 杰瑞】"];
[thread1 start];
[thread2 start];
}
- (void)deadLock1 {
[self.lock1 lock];
NSLog(@"%@ 鎖住 lock1", [NSThread currentThread]);
// 線程休眠一秒
[NSThread sleepForTimeInterval:1];
[self.lock2 lock];
NSLog(@"%@ 鎖住 lock2", [NSThread currentThread]);
[self doSomething];
[self.lock2 unlock];
NSLog(@"%@ 解鎖 lock2", [NSThread currentThread]);
[self.lock1 unlock];
NSLog(@"%@ 解鎖 lock1", [NSThread currentThread]);
}
- (void)deadLock2 {
[self.lock2 lock];
NSLog(@"%@ 鎖住 lock2", [NSThread currentThread]);
// 線程休眠一秒
[NSThread sleepForTimeInterval:1];
[self.lock1 lock];
NSLog(@"%@ 鎖住 lock1", [NSThread currentThread]);
[self doSomething];
[self.lock1 unlock];
NSLog(@"%@ 解鎖 lock1", [NSThread currentThread]);
[self.lock2 unlock];
NSLog(@"%@ 解鎖 lock2", [NSThread currentThread]);
}