iOS 开发中,线程(Thread)和进程(Process)区别和联系以及互相通信

461 阅读5分钟

在 iOS 开发中,线程(Thread)和进程(Process)是并发编程中的两个核心概念,它们的区别和联系如下:


一、区别与联系

特性进程 (Process)线程 (Thread)
资源分配独立内存空间,资源隔离共享进程的内存和资源
独立性崩溃不影响其他进程线程崩溃可能导致整个进程终止
通信方式进程间通信(IPC):XPC、Mach Ports 等直接共享内存,但需同步(锁、信号量等)
创建开销大(需要分配独立资源)小(共享进程资源)
iOS 应用场景每个 App 是一个进程主线程(UI)、后台线程(网络、计算等)

联系

  1. 线程是进程的执行单元,一个进程至少包含一个主线程。
  2. 两者都用于实现并发执行,但线程更轻量级。

二、代码示例

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)")
}

三、关键总结

  1. 线程:轻量级,共享进程资源,用于 App 内部的并发任务(如网络请求、计算)。
  2. 进程:重量级,独立资源隔离,用于系统级服务或复杂隔离需求。
  3. iOS 多线程工具:GCD、OperationQueue、Thread。
  4. 进程间通信: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 降低复杂度。