dispatch_object_t
GCD
全部類的基類 dispatch_object_t
是一個聯合體(並且是一個透明聯合體),就是dispatch_object_t
能夠是結構體中的任意一種類型,大小爲這些數據類型中最大的數據類型的大小_os_object_s
dispatch_object_s
dispatch_continuation_s
dispatch_continuation_s
結構體主要封裝block
和function
,dispatch_async
中的block
最終都會封裝成這個數據類型 dispatch_group_s
dispatch_queue_s
dispatch_queue_create
源碼libdispatch.dylib
庫中,而後下載libdispatch.dylib
源碼搜索dispatch_queue_create
能夠找到_dispatch_lane_create_with_target
函數來實現建立_dispatch_lane_create_with_target
源碼_dispatch_get_root_queue
方法獲取目標隊列_dispatch_get_root_queue(0, true)
函數獲取目標隊列,獲取到的目標隊列是_dispatch_root_queues[DISPATCH_ROOT_QUEUE_IDX_DEFAULT_OVERCOMMIT_PRIORITY]
。_dispatch_get_root_queue(0, false)
函數獲取目標隊列,獲取到的目標隊列是_dispatch_root_queues[DISPATCH_ROOT_QUEUE_IDX_DEFAULT_PRIORITY]
。_dispatch_object_alloc
開闢空間建立隊列_dispatch_queue_init
初始化隊列,這裏根據第一步規範後的參數判斷設置最大併發數,DISPATCH_QUEUE_WIDTH_MAX
從這裏也能夠知道最大的併發數是4094_dispatch_continuation_init
任務包裝函數_dispatch_continuation_init_f
函數賦值func、ctxt等參數 _dispatch_continuation_async
併發處理函數dx_push
發現是個宏#define dx_push(x, y, z) dx_vtable(x)->dq_push(x, y, z)
,發現仍是調用了dq_push
方法繼續全局搜索dq_push
dq_push
方法有不少個不過每一個上面有類型不難猜想異步函數應該對應的是queue_concurrent
下的方法對應的方法是_dispatch_lane_concurrent_push
這裏能夠經過下符號斷點來驗證首先如今異步函數錢下個斷點_dispatch_lane_concurrent_push
的方法堆棧上因此也驗證了上述猜測_dispatch_lane_concurrent_push
_dispatch_continuation_redirect_push
方法這裏也能夠經過添加符號斷點來驗證_dispatch_lane_concurrent_push
方法執行完成以後直接進入到_dispatch_continuation_redirect_push
方法而後就執行了任務繼續全局搜索_dispatch_continuation_redirect_push
方法dq_push
對應的就不是_dispatch_lane_concurrent_push
方法了由於對應的隊列類型變成了跟隊列,因此此時應該對應的是_dispatch_root_queue_push
方法一樣的也能夠根據上述的步驟下一個符號斷點來驗證,繼續全局搜索_dispatch_root_queue_push
方法_dispatch_root_queue_push_override
符號斷點在下一個_dispatch_root_queue_push_inline
符號斷點發現會走到_dispatch_root_queue_push_override
方法中而後_dispatch_root_queue_push_inline
方法_dispatch_root_queue_poke
方法_dispatch_root_queue_poke_slow
方法_dispatch_root_queues_init
方法點進去發現發現是dispatch_once_f
方法調用func
是_dispatch_root_queues_init_once
_dispatch_worker_thread2
(線程的執行是系統底層去出發的,這裏只須要綁定線程,系統會去觸發線程)方法查看源碼_dispatch_root_queue_drain
方法源碼dispatch_sync
源碼_dispatch_sync_f
源碼dispatch_barrier_sync
源碼以下:_dispatch_sync_f_slow
方法中處理的__DISPATCH_WAIT_FOR_QUEUE__
方法_dq_state_drain_locked_by
方法源碼dispatch_once
查看源碼_dispatch_Block_invoke
就是一個宏#define _dispatch_Block_invoke(bb) \ ((dispatch_function_t)((struct Block_layout *)bb)->invoke)
就是invoke方法dispatch_semaphore_create
建立信號量,指定最大併發數dispatch_semaphore_signal
發送信號dispatch_semaphore_wait
等待信號- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t sem = dispatch_semaphore_create(2);
//任務1
dispatch_async(queue, ^{
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
NSLog(@"執行任務1");
sleep(1);
NSLog(@"任務1完成");
dispatch_semaphore_signal(sem);
});
//任務2
dispatch_async(queue, ^{
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
NSLog(@"執行任務2");
sleep(1);
NSLog(@"任務2完成");
dispatch_semaphore_signal(sem);
});
//任務3
dispatch_async(queue, ^{
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
NSLog(@"執行任務3");
sleep(1);
NSLog(@"任務3完成");
dispatch_semaphore_signal(sem);
});
}
複製代碼
打印結果以下:dispatch_semaphore_create
dispatch_semaphore_t
結構體 dispatch_semaphore_wait
os_atomic_dec2o
是個宏,由於裏面是一個一個宏嵌套,因此這裏一個一個剖析後以下; os_atomic_dec2o(dsema, dsema_value, acquire);
os_atomic_sub2o(dsema, dsema_value, 1, acquire)
os_atomic_sub(&(dsema)->dsema_value, (1), acquire)
_os_atomic_c11_op(&(dsema)->dsema_value, (1), acquire, sub, -)
atomic_fetch_sub_explicit(&(dsema)->dsema_value, 1)
等價於&(dsema)->dsema_value = &(dsema)->dsema_value -1
複製代碼
dispatch_semaphore_signal
dispatch_semaphore_wait
相反,主要是對併發量進行加加操做 dispatch_group_create
建立組dispatch_group_async
進組任務dispatch_group_notify
等待任務執行完成通知dispatch_group_wait
暫停當前線程(阻塞當前線程),等待指定的 group 中的任務執行完成後,纔會往下繼續執行dispatch_group_enter
標誌着一個任務追加到 group,執行一次,至關於group 中未執行完畢任務數+1dispatch_group_leave
標誌着一個任務離開了 group,執行一次,至關於 group 中未執行完畢任務數-1。dispatch_group_leave
和dispatch_group_enter
須要成對出現複製代碼
打印狀況: dispatch_group_wait
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_enter(group);
dispatch_async(queue, ^{
sleep(1);
NSLog(@"任務1執行完成");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務2執行完成");
dispatch_group_leave(group);
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(3);
NSLog(@"任務3執行完成");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務一、2執行完成");
});
NSLog(@"任務6執行完成(主線程)");
複製代碼
打印結果: dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務一、2執行完成");
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
sleep(1);
NSLog(@"任務1執行完成");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務2執行完成");
dispatch_group_leave(group);
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(3);
NSLog(@"任務3執行完成");
});
NSLog(@"任務6執行完成(主線程)");
複製代碼
打印結果: dispatch_group_leave
就會執行通知dispatch_group_enter
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_enter(group);
dispatch_async(queue, ^{
sleep(1);
NSLog(@"任務1執行完成");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務2執行完成");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(3);
NSLog(@"任務3執行完成");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務一、2執行完成");
});
NSLog(@"任務6執行完成(主線程)");
複製代碼
打印狀況: dispatch_group_notify
一直都不會執行dispatch_group_leave
dispatch_group_leave
和dispatch_group_enter
必定要成對出現dispatch_group_create
dispatch_group_enter
dispatch_group_leave
dispatch_group_async
dispatch_group_enter
和dispatch_group_leave
兩個方法的調用 dispatch_group_enter
方法 dispatch_group_leave
dispatch_group_notify
dispatch_source_merge_data
後,會執⾏ Dispatch Source
事先定義好的句柄(能夠把句柄簡單理解爲⼀個 block )這個過程叫Custom event,⽤戶事件。是dispatch source
⽀持處理的⼀種事件dispatch_source_create
建立源dispatch_source_set_event_handler
設置源事件回調dispatch_source_merge_data
源事件設置數據dispatch_source_get_data
獲取源事件數據dispatch_resume
繼續dispatch_suspend
掛起- (void)viewDidLoad {
[super viewDidLoad];
self.totalComplete = 0;
self.queue = dispatch_queue_create("td.com", NULL);
/*
DISPATCH_SOURCE_TYPE_DATA_ADD 自定義的事件,變量增長
DISPATCH_SOURCE_TYPE_DATA_OR 自定義的事件,變量OR
DISPATCH_SOURCE_TYPE_DATA_REPLACE 自定義的事件,變量Replace
DISPATCH_SOURCE_TYPE_MACH_SEND MACH端口發送
DISPATCH_SOURCE_TYPE_MACH_RECV MACH端口接收
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE 內存報警
DISPATCH_SOURCE_TYPE_PROC 進程監聽,如進程的退出、建立一個或更多的子線程、進程收到UNIX信號
DISPATCH_SOURCE_TYPE_READ IO操做,如對文件的操做、socket操做的讀響應
DISPATCH_SOURCE_TYPE_SIGNAL 接收到UNIX信號時響應
DISPATCH_SOURCE_TYPE_TIMER 定時器
DISPATCH_SOURCE_TYPE_VNODE 文件狀態監聽,文件被刪除、移動、重命名
DISPATCH_SOURCE_TYPE_WRITE IO操做,如對文件的操做、socket操做的寫響應
DISPATCH_MACH_SEND_DEAD
*/
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
dispatch_source_set_event_handler(self.source, ^{
NSLog(@"%@",[NSThread currentThread]);
NSUInteger value = dispatch_source_get_data(self.source);
self.totalComplete += value;
NSLog(@"進度: %.2f",self.totalComplete/100.0);
self.progressView.progress = self.totalComplete/100.0;
});
self.isRunning = YES;
dispatch_resume(self.source);
}
- (IBAction)didClickStartOrPauseAction:(id)sender {
if (self.isRunning) {
dispatch_suspend(self.source);
dispatch_suspend(self.queue);
NSLog(@"已經暫停");
self.isRunning = NO;
[sender setTitle:@"暫停中.." forState:UIControlStateNormal];
}else{
dispatch_resume(self.source);
dispatch_resume(self.queue);
NSLog(@"已經執行了");
self.isRunning = YES;
[sender setTitle:@"暫停中.." forState:UIControlStateNormal];
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"開始了");
for (int i= 0; i<100; i++) {
dispatch_async(self.queue, ^{
if (!self.isRunning) {
NSLog(@"已經暫停");
return;
}
sleep(1);
dispatch_source_merge_data(self.source, 1);
});
}
}
複製代碼