菜单

并发

相关源文件

本文档概述了 Swift 的并发模型,该模型通过 async/await、Actor 和结构化任务实现安全高效的并行执行。它涵盖了核心组件、它们的交互以及 Swift 编译器强制执行的安全机制。

有关分布式 Actor 的信息,请参阅 分布式 Actor

核心概念

Swift 的并发模型建立在三个关键组件之上

来源

  • stdlib/public/Concurrency/Task.swift14-92: void }

    class TaskPriority { +high: TaskPriority +medium: TaskPriority +low: TaskPriority +userInitiated: TaskPriority +utility: TaskPriority +background: TaskPriority }

    Task -- TaskPriority


Tasks can be:
- **Structured**: Child tasks with a parent-child relationship, automatically managed as part of a scope
- **Unstructured**: Top-level tasks created with `Task { ... }` that exist independently 
- **Detached**: Tasks that don't inherit the parent's priority or context

Sources:
- <FileRef file-url="https://github.com/swiftlang/swift/blob/721944a9/stdlib/public/Concurrency/Task.swift#L142-L151" min=142 max=151 file-path="stdlib/public/Concurrency/Task.swift">Hii</FileRef>"| ActorA
        Task2 -->|"await (suspended)<br>(waiting for access)"| ActorA
        Task3 -->|"await (suspended)<br>(waiting for access)"| ActorA
        
        ActorMailbox["Actor Mailbox<br>Message Queue"]
        ActorA --- ActorMailbox
        ActorMailbox --- Task2
        ActorMailbox --- Task3
    end

主要特性

  • 从 Actor 外部调用 Actor 的方法时,这些方法隐式地是异步的
  • Actor 的属性只能在 Actor 内部直接访问
  • @MainActor 这样的全局 Actor 提供全局隔离域

来源

// 非结构化任务 let task = Task { return await performComputation() } let result = await task.value

// 分离任务 let task = Task.detached { return await performBackgroundWork() }


When a task is created, it is scheduled on an executor and will run when resources are available.

Sources:
- <FileRef file-url="https://github.com/swiftlang/swift/blob/721944a9/stdlib/public/Concurrency/Task.swift#L597-L644" min=597 max=644 file-path="stdlib/public/Concurrency/Task.swift">Hii</FileRef>"]
        Medium["medium<br>(0x15)"]
        Low["low / utility<br>(0x11)"]
        Background["background<br>(0x09)"]
        
        High --> Medium
        Medium --> Low
        Low --> Background
    end

子任务默认继承父任务的优先级。系统内置了优先级反转保护,以防止低优先级任务阻塞高优先级任务。

来源

来源


Cancellation propagates to child tasks automatically. Tasks can:
- Check for cancellation with `Task.checkCancellation()`
- Register cancellation handlers with `withTaskCancellationHandler()`
- Respond to cancellation by returning early, throwing, or cleaning up resources

Sources:
- <FileRef file-url="https://github.com/swiftlang/swift/blob/721944a9/stdlib/public/Concurrency/Task.swift#L197-L237" min=197 max=237 file-path="stdlib/public/Concurrency/Task.swift">Hii</FileRef>"| ChildTask1
    ChildTask2 -->|"withTaskLocal { x = 2 }"| ChildTask2
    GrandChildTask -->|"x = 1 (inherited from parent)"| GrandChildTask

任务本地值

  • 使用 @TaskLocal 属性定义
  • 被子任务继承
  • 可以使用 withTaskLocal() 在特定作用域内绑定
  • 适用于传播跟踪 ID 或事务上下文等上下文信息

来源

  • stdlib/public/Concurrency/TaskLocal.swift32-52"] NonIsolated["非隔离域
    (异步访问)"]

      ActorDef -->|"defines isolation domain"| Isolated
      NonIsolated -->|"await"| Isolated
      
      IsolatedProp["actor var property"]
      IsolatedMethod["func method()"]
      NonIsolatedMethod["nonisolated func method()"]
      
      ActorDef --- IsolatedProp
      ActorDef --- IsolatedMethod
      ActorDef --- NonIsolatedMethod
      
      IsolatedProp --- Isolated
      IsolatedMethod --- Isolated
      NonIsolatedMethod --- NonIsolated
    

    end


Actor isolation rules:
- Actor properties can only be accessed directly from within the actor
- Actor methods are implicitly isolated to the actor
- Methods marked with `nonisolated` can be called synchronously from outside
- Calling an actor method from outside requires `await`
- Access to actor state from outside is implicitly asynchronous

Sources:
- <FileRef file-url="https://github.com/swiftlang/swift/blob/721944a9/test/Concurrency/actor_isolation.swift#L36-L87" min=36 max=87 file-path="test/Concurrency/actor_isolation.swift">Hii</FileRef>"]
        MainActorProp["@MainActor var property"]
        CustomActorCode["@CustomGlobalActor func customFunc()"]
        
        MainActor --- MainActorCode
        MainActor --- MainActorProp
        GlobalActorDef --- CustomActorCode
    end

常见的全局 Actor

  • @MainActor: 确保代码在主线程/队列上运行
  • 使用 @globalActor 定义的自定义全局 Actor

全局 Actor 可以应用于

  • 函数和方法
  • 属性
  • 类型(类、结构体、枚举)
  • 扩展

来源

  • test/Concurrency/global_actor_inference.swift36-47 Actor->>ExternalService: await service.fetch() Actor-->>Client: Actor is now available Client->>Actor: call method2() Actor->>Actor: execute method2() Actor-->>Client: return from method2() ExternalService-->>Actor: return result Actor->>Actor: continue method1() Actor-->>Client: return from method1()

Reentrancy considerations:
- Can cause subtle bugs if actor state is inconsistent between entries
- Actor isolation still ensures only one task runs actor code at a time
- Careful consideration needed for methods that modify state before awaiting

Sources:
- <FileRef file-url="https://github.com/swiftlang/swift/blob/721944a9/stdlib/public/Concurrency/Actor.cpp#L96-L134" min=96 max=134 file-path="stdlib/public/Concurrency/Actor.cpp">Hii</FileRef>"]
        SendableClasses["@Sendable Classes"]
        FinalClasses["Final Classes with Sendable Properties"]
        UncheckedSendable["@unchecked Sendable Types"]
        
        SendableProtocol --- ValueTypes
        SendableProtocol --- SendableClasses
        SendableProtocol --- FinalClasses
        SendableProtocol --- UncheckedSendable
        
        CrossActor["Cross-Actor References"]
        SendableProtocol -->|"required for"| CrossActor
    end

Sendable 检查

  • 具有 Sendable 属性的值类型自动是 Sendable
  • 类必须显式标记 @Sendable
  • 只有 Sendable 属性的 Final 类可以符合 Sendable
  • 无法静态验证的类型使用 @unchecked Sendable

来源

  • lib/Sema/TypeCheckConcurrency.cpp879-955"] DifferentActor["不同 Actor
    (需要 Await)"] NonIsolated["非隔离上下文
    (需要 Await)"]

      IsolationCheck -->|"allowed"| SameActor
      IsolationCheck -->|"enforced"| DifferentActor
      IsolationCheck -->|"enforced"| NonIsolated
      
      SyncAccess["Synchronous Access Attempt"]
      AsyncAccess["Asynchronous Access"]
      
      DifferentActor --- SyncAccess
      NonIsolated --- SyncAccess
      DifferentActor --- AsyncAccess
      NonIsolated --- AsyncAccess
      
      SyncAccess -->|"compile error"| Error["Error: actor-isolated property cannot be referenced"]
      AsyncAccess -->|"allowed"| Valid["Valid: await actor.property"]
    

    end


The compiler checks:
- Access to actor properties and methods
- Crossing actor boundaries with proper `await`
- Preventing data races by enforcing isolation

Sources:
- <FileRef file-url="https://github.com/swiftlang/swift/blob/721944a9/lib/Sema/TypeCheckConcurrency.cpp#L235-L269" min=235 max=269 file-path="lib/Sema/TypeCheckConcurrency.cpp">Hii</FileRef>"]
        Add["group.addTask { ... }"]
        Next["await group.next()"]
        Cancel["group.cancelAll()"]
        Loop["for await result in group { ... }"]
        
        Group -->|"1. create group"| Add
        Add -->|"2. add tasks"| Add
        Add -->|"3. collect results"| Next
        Next -->|"continue collecting"| Next
        Next -->|"or"| Loop
        Next -->|"4. optionally"| Cancel
        Loop -->|"5. group scope exits"| Complete["All tasks complete"]
    end

任务组有两种变体

  • withTaskGroup: 用于非抛出子任务
  • withThrowingTaskGroup: 用于可能抛出错误的子任务

来源

  • stdlib/public/Concurrency/TaskGroup.swift65-125 Add["group.addTask { ... }"] Cancel["group.cancelAll()"]

      Group -->|"create group"| Add
      Add -->|"add more tasks"| Add
      Add -->|"optionally"| Cancel
      Group -->|"group scope exits<br>results discarded"| Complete["All tasks complete<br>(results ignored)"]
    

    end


Discarding task groups are useful when:
- Task side effects are more important than return values
- You need to limit memory usage by not accumulating results
- The only relevant outcome is whether tasks completed or failed

Sources:
- <FileRef file-url="https://github.com/swiftlang/swift/blob/721944a9/stdlib/public/Concurrency/DiscardingTaskGroup.swift#L15-L25" min=15 max=25 file-path="stdlib/public/Concurrency/DiscardingTaskGroup.swift">Hii</FileRef>"]
        Reading["let id = contextID"]
        ChildTask["Task { ... contextID ... }"]
        
        Declaration -->|"define"| Binding
        Binding -->|"set value in scope"| Reading
        Binding -->|"inherits value"| ChildTask
    end

任务本地值用于

  • 在服务器应用程序中传播请求上下文
  • 跟踪日志记录和跟踪的操作 ID
  • 在异步操作中维护身份验证上下文

来源


Key characteristics:
- Creates a child task that executes concurrently
- Results are awaited when accessed
- Automatically managed as part of structured concurrency
- Errors propagate to the parent task

Sources:
- <FileRef file-url="https://github.com/swiftlang/swift/blob/721944a9/stdlib/public/Concurrency/AsyncLet.cpp#L1-L16" min=1 max=16 file-path="stdlib/public/Concurrency/AsyncLet.cpp">Hii</FileRef>"]
        
        API -->|"uses"| Runtime
        Runtime -->|"implements"| Executor
        Runtime -->|"implements"| Scheduling
        Executor -->|"leverages"| PlatformIntegration
        Scheduling -->|"leverages"| PlatformIntegration
    end

运行时处理

  • 任务的创建和管理
  • 执行器的实现
  • 任务调度和优先级
  • Actor 隔离强制执行
  • 与平台设施的集成(如 Apple 平台上的 GCD)

来源

  • [include/swift/Runtime/Concurrency.h:18-64](
  • [stdlib/public/Concurrency/TaskPrivate.h:17-40](
  • [stdlib/public/Concurrency/CompatibilityOverrideConcurrency.def:1-31](

结论

Swift 的并发模型提供了一种全面的、类型安全的并发编程方法。通过将任务、Actor 和 async/await 与编译时强制执行的隔离和 Sendable 机制相结合,Swift 使编写正确的并发代码更加容易。该系统内置的结构化并发、任务管理和 Actor 隔离功能有助于防止常见并发错误,如数据竞争、死锁和优先级反转。

并发系统与 Swift 的类型系统深度集成,尽可能提供在编译时检查的安全保证。与使用线程和锁的传统方法相比,这使得并发代码更加可靠且易于理解。