1. 死鎖
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"--執(zhí)行任務--");
});
}
發(fā)生死鎖
原因:dispatch_sync
會將任務追加到隊列上,等當前的任務執(zhí)行完畢,再執(zhí)行Block中的任務灸叼;但是當前執(zhí)行的任務viewDidLoad
包含Block任務,所以會造成死鎖。
2. dispatch_apply
dispatch_apply
函數按照指定的次數將指定的Block追加到指定的Dispatch Queue中蜜另,并等待全部執(zhí)行完成;
NSArray *array = @[@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J"];
dispatch_apply([array count], dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
NSLog(@"index:%zu : value : %@", index, [array objectAtIndex:index]);
});
NSLog(@"--End--");
結果
結果:由于我用的是Global Queue嫡意,所以會亂序輸出結果举瑰,并在所有結果輸出完畢后,輸出End
3. Dispatch Semaphore
當并行執(zhí)行的處理更新數據時蔬螟,會產生數據不一樣的情況此迅,有時甚至會導致程序崩潰,雖然我們可以采用dispatch_group
旧巾、dispatch_barrier_async
等函數來避免這些問題耸序,但有必要進行更細力度的排他控制
信號量的使用:
- 創(chuàng)建一個計數初始值為1的信號量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
- 當信號量的計數值大于或等于1時,將計數值減1鲁猩,并執(zhí)行下面的代碼坎怪;當信號量的計數值等于0時,等待
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- 增加指定的信號量的計數值
dispatch_semaphore_signal(semaphore);
實例:向一個數組中寫入10萬條數據
NSMutableArray *mutableArray = [NSMutableArray array];
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100000; i ++) {
dispatch_async(globalQueue, ^{
[mutableArray addObject:[NSNumber numberWithInt:i]];
NSLog(@"--");
});
}
上面的代碼會因為內存過于頻繁釋放導致崩潰绳匀,提示
pointer being freed was not allocated
解決方法:加入信號量
NSMutableArray *mutableArray = [NSMutableArray array];
//定義一個計數值為1的信號量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100000; i ++) {
dispatch_async(globalQueue, ^{
//如果信號量的值大于等于1芋忿,執(zhí)行寫入操作;如果計數值等于0疾棵,則等待
//這樣即使有多條線程來操作數組戈钢,也會因為信號量為0而被擋在門外
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[mutableArray addObject:[NSNumber numberWithInt:i]];
NSLog(@"--");
//當某一條線程的寫入操作完成,才能允許下一個線程進行寫操作是尔,此時要對信號量的計數值 +1
dispatch_semaphore_signal(semaphore);
});
}
從上面看來殉了,信號量最主要的應用就是控制線程數量,再來一個更明顯的例子
NSMutableArray *mutableArray = [NSMutableArray array];
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100000; i ++) {
dispatch_async(globalQueue, ^{
NSLog(@"%d", i);
});
}
當利用多線程讀取數據時拟枚,如果不對線程數量進行控制薪铜,會產生大量線程众弓,給程序帶來過重的負荷,顯然是不合理的隔箍;
此時就可以采用信號量谓娃,合理控制線程數量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(5);
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100000; i ++) {
//當第六個線程來訪問的時候,semaphore的計數值為0蜒滩,不允許
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(globalQueue, ^{
NSLog(@"%d", i);
});
//當某個線程完成一次操作滨达,可允許下一個線程來操作
dispatch_semaphore_signal(semaphore);
}