You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Actor内多Task可访问变量?并行运行会引发数据竞争吗?编译器为何未阻止?

Swift 并发疑问解答

针对你提出的三个问题,结合代码逐一说明:

1. 为何能从多个Task中访问变量?

你代码里的Actor1是普通class,不是Swift的actor类型(正确声明Actor需要用actor关键字,而非class)。普通类没有Actor特有的并发隔离机制,它的属性可以被任意Task直接访问,不管这些Task是不是在类的方法内部创建的。

2. 两个Task为何会并行运行?

performAsyncTasks是async方法,其中创建的两个Task会被系统调度到全局并发执行池中的不同线程上,自然会并行运行。如果Actor1是真正的actor类型,在其内部创建的Task默认会绑定到Actor的串行执行器,两个Task会串行执行而非并行——这正是Actor保证并发安全的核心机制之一。

3. 多次访问value是否会引发数据竞争?为何编译器未阻止该操作?

会引发数据竞争!value +=1不是原子操作,它包含「读取当前值→加1→写入新值」三个步骤。两个并行的Task同时执行这个操作时,会出现互相覆盖的情况,最终value的结果会小于预期的20000。

编译器没有阻止,是因为你用的是普通class,Swift的并发安全检查仅针对标记为actor、@MainActor或其他并发隔离类型的代码。普通class的属性访问默认不做并发安全校验,需要开发者自行通过锁、Actor或原子类型来保证线程安全。

修正后的示例代码(真正的Actor实现)

如果要实现无数据竞争的版本,需要把Actor1改成真正的Actor:

import SwiftUI

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView().task {
                await Actor1().performAsyncTasks()
            }
        }
    }
}

// 用actor关键字声明,而非class
actor Actor1 {
    var value = 0
    
    func performAsyncTasks() async {
        // 两个Task会在Actor的串行执行器上运行,不会并行
        Task {
            for i in 1...10_000 {
                print("In Task 1: \(i)")
                value += 1
            }
        }
        
        Task {
            for i in 1...10_000 {
                print("In Task 2: \(i)")
                value += 1
            }
        }
    }
}

此时两个Task会串行执行,value最终会正确得到20000,也不会有数据竞争。

内容的提问来源于stack exchange,提问作者MaxFactorHub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:13:21