在 iOS 开发中,线程(Thread)和进程(Process)是并发编程中的两个核心概念,它们的区别和联系如下:
一、区别与联系
| 特性 | 进程 (Process) | 线程 (Thread) |
|---|---|---|
| 资源分配 | 独立内存空间,资源隔离 | 共享进程的内存和资源 |
| 独立性 | 崩溃不影响其他进程 | 线程崩溃可能导致整个进程终止 |
| 通信方式 | 进程间通信(IPC):XPC、Mach Ports 等 | 直接共享内存,但需同步(锁、信号量等) |
| 创建开销 | 大(需要分配独立资源) | 小(共享进程资源) |
| iOS 应用场景 | 每个 App 是一个进程 | 主线程(UI)、后台线程(网络、计算等) |
联系:
- 线程是进程的执行单元,一个进程至少包含一个主线程。
- 两者都用于实现并发执行,但线程更轻量级。
二、代码示例
1. 线程(Thread)
Objective-C
// 使用 GCD(Grand Central Dispatch)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 后台线程执行耗时任务
NSLog(@"GCD Thread: %@", [NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程更新 UI
NSLog(@"Main Thread: %@", [NSThread currentThread]);
});
});
// 使用 NSThread
NSThread *thread = [[NSThread alloc] initWithBlock:^{
NSLog(@"Custom Thread: %@", [NSThread currentThread]);
}];
[thread start];
Swift
// 使用 GCD
DispatchQueue.global(qos: .background).async {
// 后台线程执行耗时任务
print("GCD Thread: (Thread.current)")
DispatchQueue.main.async {
// 回到主线程更新 UI
print("Main Thread: (Thread.current)")
}
}
// 使用 Thread 类
let customThread = Thread {
print("Custom Thread: (Thread.current)")
}
customThread.start()
2. 进程(Process)
在 iOS 中,一个 App 默认是单进程的。多进程通常用于系统级服务(如扩展、XPC 服务),但开发者极少直接创建新进程。以下是一个简单的 进程间通信(XPC) 示例:
Objective-C
// 客户端进程
NSXPCConnection *connection = [[NSXPCConnection alloc] initWithServiceName:@"com.example.xpc-service"];
connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCServiceProtocol)];
[connection resume];
// 调用远程进程的方法
id<XPCServiceProtocol> service = [connection remoteObjectProxyWithErrorHandler:^(NSError *error) {
NSLog(@"XPC Error: %@", error);
}];
[service doTaskWithCompletion:^(NSString *result) {
NSLog(@"Received result: %@", result);
}];
Swift
// 客户端进程
let connection = NSXPCConnection(serviceName: "com.example.xpc-service")
connection.remoteObjectInterface = NSXPCInterface(with: XPCServiceProtocol.self)
connection.resume()
// 调用远程进程的方法
guard let service = connection.remoteObjectProxy as? XPCServiceProtocol else { return }
service.doTasks { result in
print("Received result: (result)")
}
三、关键总结
- 线程:轻量级,共享进程资源,用于 App 内部的并发任务(如网络请求、计算)。
- 进程:重量级,独立资源隔离,用于系统级服务或复杂隔离需求。
- iOS 多线程工具:GCD、OperationQueue、Thread。
- 进程间通信:XPC 是苹果推荐的 IPC 方式。
四、线程间通信
线程间共享同一进程的内存空间,可以直接访问变量,但需要同步机制确保线程安全。
1. 共享变量 + 锁(Lock)
Objective-C
// 共享变量
__block int sharedValue = 0;
NSLock *lock = [[NSLock alloc] init];
// 线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lock];
sharedValue = 42;
[lock unlock];
});
// 线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lock];
NSLog(@"Value: %d", sharedValue); // 输出 42
[lock unlock];
});
Swift
var sharedValue = 0
let lock = NSLock()
// 线程1
DispatchQueue.global().async {
lock.lock()
sharedValue = 42
lock.unlock()
}
// 线程2
DispatchQueue.global().async {
lock.lock()
print("Value: (sharedValue)") // 输出 42
lock.unlock()
}
2. 通过 GCD 队列传递数据(串行队列)
Objective-C
// 创建一个串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.example.serialQueue", DISPATCH_QUEUE_SERIAL);
// 线程1:提交任务到队列
dispatch_async(serialQueue, ^{
NSInteger value = 100;
NSLog(@"Thread 1 sends: %ld", (long)value);
});
// 线程2:从队列中读取(自动同步)
dispatch_async(serialQueue, ^{
NSLog("Thread 2 received data");
});
Swift
let serialQueue = DispatchQueue(label: "com.example.serialQueue")
// 线程1
serialQueue.async {
let value = 100
print("Thread 1 sends: (value)")
}
// 线程2
serialQueue.async {
print("Thread 2 received data")
}
3. 通过主线程更新 UI
Objective-C
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 后台线程执行任务
NSString *result = @"Data from background";
// 通过主线程更新 UI
dispatch_async(dispatch_get_main_queue(), ^{
self.label.text = result;
});
});
Swift
DispatchQueue.global().async {
// 后台线程执行任务
let result = "Data from background"
// 通过主线程更新 UI
DispatchQueue.main.async {
self.label.text = result
}
}
五、进程间通信(IPC)
进程间无法直接共享内存,需要借助系统提供的 IPC 机制。
1. XPC(推荐方式)
XPC 是苹果官方推荐的 IPC 方案,适用于 App 与扩展(Extension)或守护进程通信。
Objective-C
// 客户端(调用方)
NSXPCConnection *connection = [[NSXPCConnection alloc] initWithServiceName:@"com.example.XPCService"];
connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCServiceProtocol)];
[connection resume];
// 调用远程方法
id<XPCServiceProtocol> service = [connection remoteObjectProxyWithErrorHandler:^(NSError *error) {
NSLog(@"XPC Error: %@", error);
}];
[service processData:@"Hello from App" reply:^(NSString *response) {
NSLog(@"Received response: %@", response);
}];
Swift
// 客户端(调用方)
let connection = NSXPCConnection(serviceName: "com.example.XPCService")
connection.remoteObjectInterface = NSXPCInterface(with: XPCServiceProtocol.self)
connection.resume()
// 调用远程方法
guard let service = connection.remoteObjectProxy as? XPCServiceProtocol else { return }
service.processData("Hello from App") { response in
print("Received response: (response)")
}
2. 共享文件 + NSFileCoordinator
通过共享文件实现数据交换,需使用 NSFileCoordinator 保证文件访问安全。
Objective-C
// 写入进程
NSURL *fileURL = [NSURL fileURLWithPath:@"/path/to/shared/file.txt"];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[coordinator coordinateWritingItemAtURL:fileURL options:0 error:nil byAccessor:^(NSURL *newURL) {
[@"Data from Process A" writeToURL:newURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
}];
// 读取进程
[coordinator coordinateReadingItemAtURL:fileURL options:0 error:nil byAccessor:^(NSURL *newURL) {
NSString *content = [NSString stringWithContentsOfURL:newURL encoding:NSUTF8StringEncoding error:nil];
NSLog(@"Received: %@", content);
}];
Swift
// 写入进程
let fileURL = URL(fileURLWithPath: "/path/to/shared/file.txt")
let coordinator = NSFileCoordinator()
coordinator.coordinate(writingItemAt: fileURL, options: .forReplacing, error: nil) { newURL in
try? "Data from Process A".write(to: newURL, atomically: true, encoding: .utf8)
}
// 读取进程
coordinator.coordinate(readingItemAt: fileURL, options: .withoutChanges, error: nil) { newURL in
if let content = try? String(contentsOf: newURL, encoding: .utf8) {
print("Received: (content)")
}
}
3. Mach Ports(底层 API)
Mach Ports 是 macOS/iOS 的底层 IPC 机制,但直接使用较复杂(通常优先选择 XPC)。
六、关键总结
| 通信类型 | 方式 | 特点 | 适用场景 |
|---|---|---|---|
| 线程间 | 共享变量 + 锁 | 直接但需同步 | 简单数据共享 |
| 线程间 | GCD 队列 | 自动同步,避免竞态条件 | 任务调度和数据传递 |
| 进程间 | XPC | 安全、苹果官方推荐 | App 与扩展、守护进程通信 |
| 进程间 | 共享文件 + 文件协调器 | 适用于大文件或持久化数据 | 跨进程文件共享 |
- 优先选择 GCD/XPC:线程间用 GCD 队列,进程间用 XPC。
- 避免直接共享内存:除非必要,否则使用高层 API 降低复杂度。