Jon*_*Fir 4 macos xcode multithreading nsrunloop swift
我用 RunLoop 做实验。我正在创建简单的 Mac OS 控制台应用程序并且只调用一行代码。
RunLoop.current.run()
Run Code Online (Sandbox Code Playgroud)
之后在调试导航器出现第二个线程。为什么?
Grand Central Dispatch (GCD) 提供了一个“主队列”(在 Swift 中使用 访问DispatchQueue.main)。主队列总是在主线程上运行它的块。
由于 Apple 平台RunLoop.main上的应用程序通常在主线程上运行,因此运行循环与 GCD 一起运行添加到主队列中的块。
所以,当主线程的运行循环被创建时,它会创建一些 GCD 对象,这使得 GCD 初始化自己。GCD 初始化的一部分涉及创建一个“工作队列”和一个线程池,用于运行添加到工作队列中的作业。
您可以看到,创建线程的是运行循环的创建,而不是它的运行。这是一个示例程序:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
[NSRunLoop currentRunLoop]; // line 4
return 0; // line 5
}
Run Code Online (Sandbox Code Playgroud)
在终端中,我运行 lldb(调试器)。我告诉它调试test程序,在第 4 行设置断点,然后运行。当它在断点处停止时(在调用 之前currentRunLoop,我列出了所有线程:
:; lldb
"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help
(lldb) target create test
Current executable set to 'test' (x86_64).
(lldb) b 4
Breakpoint 1: where = test`main + 22 at main.m:4, address = 0x0000000100000f46
(lldb) r
Process 12087 launched: '/Users/mayoff/Library/Developer/Xcode/DerivedData/test-aegotyskrtnbeabaungzpkkbjvdz/Build/Products/Debug/test' (x86_64)
Process 12087 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: sp=0x00007fff5fbff240 fp=0x00007fff5fbff260 pc=0x0000000100000f46 test`main(argc=1, argv=0x00007fff5fbff280) + 22 at main.m:4
1 #import <Foundation/Foundation.h>
2
3 int main(int argc, const char * argv[]) {
-> 4 [NSRunLoop currentRunLoop]; // line 4
5 return 0; // line 5
6 }
Target 0: (test) stopped.
(lldb) thread list
Process 12087 stopped
* thread #1: tid = 0x1066d3, 0x0000000100000f46 test`main(argc=1, argv=0x00007fff5fbff280) at main.m:4, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
Run Code Online (Sandbox Code Playgroud)
只有一根线。接下来,我跳过调用currentRunLoop并再次列出所有线程:
(lldb) n
Process 12087 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
frame #0: sp=0x00007fff5fbff240 fp=0x00007fff5fbff260 pc=0x0000000100000f69 test`main(argc=1, argv=0x00007fff5fbff280) + 57 at main.m:5
2
3 int main(int argc, const char * argv[]) {
4 [NSRunLoop currentRunLoop]; // line 4
-> 5 return 0; // line 5
6 }
Target 0: (test) stopped.
(lldb) thread list
Process 12087 stopped
* thread #1: tid = 0x1066d3, 0x0000000100000f69 test`main(argc=1, argv=0x00007fff5fbff280) at main.m:5, queue = 'com.apple.main-thread', stop reason = step over
thread #2: tid = 0x106ab3, 0x00007fffc942c070 libsystem_pthread.dylib`start_wqthread
thread #3: tid = 0x106ab4, 0x00007fffc934244e libsystem_kernel.dylib`__workq_kernreturn + 10
thread #4: tid = 0x106ab5, 0x00007fffc8923e85 libobjc.A.dylib`class_createInstance + 142, queue = 'com.apple.root.default-qos.overcommit'
Run Code Online (Sandbox Code Playgroud)
现在有四个线程,其中一些在初始化过程中停止。
“但是 Rob,”你说,“当我test在 Xcode 中运行并在调用之前停止时currentRunLoop,它已经有四个线程了!” 如图所示:
“确实如此,”我回答。如果您运行菜单项 Debug > Debug Workflow > Shared Libraries...,然后在过滤器框中键入 Xcode,您会发现原因:
当您在 Xcode 下运行程序时,Xcode 会在您的进程中注入一些额外的共享库,以提供额外的调试支持。这些共享库包括在您的代码运行之前运行的初始化代码,并且该初始化代码对 GCD 执行某些操作,因此 GCD 在您的第一行代码运行之前被初始化(创建其线程池)。
工作队列根据工作负载调整其线程池的大小。由于没有任何东西向队列添加作业,它立即将其池缩小到只有一个后台线程。这就是为什么当您查看 Xcode 的 CPU 报告时,您只会看到两个线程:运行运行循环的主线程和一个等待作业运行的工作线程。
| 归档时间: |
|
| 查看次数: |
1626 次 |
| 最近记录: |