源碼塊一:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"%@",[NSThread currentThread]);
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"Hello World");
});
}
分析:
- 當前dispatch_sync()函數在主線程中調用,可以用 NSLog(@"%@",[NSThread currentThread]); 驗證
- 調用dispatch_sync()函數會立即阻塞調用時該函數所在的線程,即主線程等待dispatch_sync()函數返回
- dispatch_sync()函數追加任務(即Block代碼塊)到主隊列dispatch_get_main_queue()中,主隊列是一種特殊的串行隊列
- 主隊列的任務在主線程中執行,但此時主線程被阻塞,無法執行Block代碼塊,導致dispatch_sync()函數無法返回,一直等待Block被主線程執行
- 最終導致死鎖
源碼塊二:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"1-----%@",[NSThread currentThread]);
//創建一個串行隊列
dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
//異步函數產生一個新的線程
dispatch_async(queue, ^{
NSLog(@"2-----%@",[NSThread currentThread]);
//向新線程中用同步函數dispatch_sync()追加任務
dispatch_sync(queue, ^{
NSLog(@"3-----%@",[NSThread currentThread]);
});
});
}
控制臺:
1-----<NSThread: 0x7ff8aad00220>{number = 1, name = main}
2-----<NSThread: 0x7ff8aad11670>{number = 2, name = (null)}
分析:
- 在產生的新的線程(number = 2 , name = (null))中,調用函數dispatch_sync(),立即阻塞當前線程,即新開的線程,此時線程阻塞,等待dispatch_sync()函數返回.
- 使用 dispatch_sync() 追加任務NSLog(@"3-----%@",[NSThread currentThread]);到隊列queue中, 但是當前線程被阻塞,無法執行Block代碼塊,Block代碼塊等待被線程執行.
- 最終導致死鎖.
源碼塊三:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"1-----%@",[NSThread currentThread]);
//創建一個串行隊列
dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
//異步函數產生一個新的線程
dispatch_async(queue, ^{
NSLog(@"2-----%@",[NSThread currentThread]);
//創建一個新的串行隊列
dispatch_queue_t queue2 = dispatch_queue_create("newQueue", DISPATCH_QUEUE_SERIAL);
//在新線程中用同步函數dispatch_sync()向新建的串行隊列中追加任務
dispatch_sync(queue2, ^{
NSLog(@"3-----%@",[NSThread currentThread]);
});
});
}
控制臺:
1-----<NSThread: 0x7fe5daf01730>{number = 1, name = main}
2-----<NSThread: 0x7fe5dac448f0>{number = 2, name = (null)}
3-----<NSThread: 0x7fe5dac448f0>{number = 2, name = (null)}
可以看到該代碼塊并沒有產生死鎖,但是queue2隊列也是在新線程中,為什么調用dispatch_sync()函數時,并沒有阻塞<NSThread: 0x7fe5dac448f0>{number = 2, name = (null)}這條線程,從而使得dispatch_sync()中的任務在新線程中被執行.
那么我的問題就是: 用異步函數創建新線程時所用到的隊列,即代碼中的queue
dispatch_async(queue, ^{
NSLog(@"2-----%@",[NSThread currentThread]);
如果為串行隊列(并發隊列并不會有該情況),那么該隊列 是否可以認為是 該新線程中的 "主隊列",類似于源碼塊一的效果.