引文:
-
GCD
-
NSOperation
-
NSThread
-
多線程與鎖
注意: 在主線程中執(zhí)行同步任務(wù)將發(fā)生死鎖
死鎖原因
系統(tǒng)在主隊列開啟主線程執(zhí)行任務(wù),用戶手動添加一個同步任務(wù)到當(dāng)當(dāng)前線程中,由于同步任務(wù)不開辟額外的線程去處理,所以就在當(dāng)前線程中去執(zhí)行任務(wù),由于當(dāng)前線程是主線程,所有就造成任務(wù)的相互等待過程從而產(chǎn)生死鎖.
同步串行
思考: 輸出什么?
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"1");
[self performSelector:@selector(test) withObject:self afterDelay:2];
NSLog(@"2"); });
}
- (void)test{
NSLog(@"test");
}
輸出: 1 2
不會輸出test.
因為
performSelector
方法要添加到對應(yīng)線程的runloop
之后才會生效,由于異步任務(wù)是在dispatch_get_global_queue
并發(fā)隊列中的, 默認(rèn)不開啟runloop
,所有不會執(zhí)行.如果是添加到主隊列中,就會執(zhí)行了.
Dispathc_barrier_async() (柵欄模式)
可以實(shí)現(xiàn)多讀單寫.
Dispatch_group_async() (組別模式)
可以實(shí)現(xiàn)多任務(wù)執(zhí)行完畢后統(tǒng)一處理后續(xù)業(yè)務(wù)邏輯
NSOperation
需要和NSOperationQueue
配合使用來實(shí)現(xiàn)多線程方案
特點(diǎn):
-
添加任務(wù)依賴
-
認(rèn)為執(zhí)行狀態(tài)控制
isReady --> 準(zhǔn)備
isExecuting --> 執(zhí)行
isFinished --> 完成
isCancelled --> 取消
如果只重寫main方法,底層控制變更任務(wù)執(zhí)行狀態(tài),以及任務(wù)的退出
如果重寫了start方法, 自行控制任務(wù)的執(zhí)行狀態(tài) 設(shè)置最大并發(fā)量
鎖
@synchronized
一般創(chuàng)建單例對象使用
atomic
修飾屬性的關(guān)鍵字
對被修飾對象進(jìn)行原子操作(不負(fù)責(zé)使用)
@property (atomic) NSMutableArray *arr;
self.arr = [NSMutableArray array]; //??
[self.arr addObject:@"1"]; // ? 不負(fù)責(zé)使用
自旋鎖(OSSpinLock)
循環(huán)等待詢問,不釋放當(dāng)前資源.
用于輕量級數(shù)據(jù)訪問
NSLock
- (void)test{
NSLock *lock = [[NSLock alloc] init];
[lock lock];
[self test2];
[lock unlock];
}
- (void)test2{
NSLock *lock = [[NSLock alloc] init];
[lock lock];
[self test3];
[lock unlock];
}
會造成死鎖 ,解決方案是使用遞歸鎖
遞歸鎖 (NSRecureiveLock)
可以無限重入
- (void)test{
NSRecursiveLock *lock = [[NSRecursiveLock alloc] init];
[lock lock];
[self test2];
[lock unlock];
}
- (void)test2{
NSRecursiveLock *lock = [[NSRecursiveLock alloc] init];
[lock lock];
// 業(yè)務(wù)邏輯
[lock unlock];
}