首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >并发执行代码中捕获变量的变异

并发执行代码中捕获变量的变异
EN

Stack Overflow用户
提问于 2022-11-09 09:50:03
回答 1查看 198关注 0票数 2

我在Swift 5.5中遇到了一个问题,我不太明白解决方案。

代码语言:javascript
复制
import Foundation

func testAsync() async {

    var animal = "Dog"

    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
        animal = "Cat"
        print(animal)
    }

    print(animal)
}

Task {
    await testAsync()
}

这段代码会导致错误。

代码语言:javascript
复制
Mutation of captured var 'animal' in concurrently-executing code

但是,如果您将animal变量从这个异步函数的上下文中移开,

代码语言:javascript
复制
import Foundation

var animal = "Dog"

func testAsync() async {
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
        animal = "Cat"
        print(animal)
    }

    print(animal)
}

Task {
    await testAsync()
}

它将汇编。我理解这个错误是为了防止数据竞争,但是为什么移动变量会使其安全?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-10 17:53:57

关于globals示例的行为,我可能会向您介绍与globals的可发送性相关的罗伯·纳皮尔的评论 re bug/限制:

编译器在如何推理全局变量方面有许多限制。简短的回答是“不要让全局变量变。”它出现在论坛上,但没有得到任何讨论。https://forums.swift.org/t/sendability-checking-for-global-variables/56515

FWIW,如果将其放在实际的应用程序中,并将“严格并发检查”构建设置更改为“完成”,则在全局示例中确实会收到适当的警告:

对var的引用不是并发安全的,因为它涉及共享的可变状态。

这种对线程安全问题的编译时检测正在发展,Swift 6中出现了许多新的错误(这就是为什么他们给了我们这个新的“严格并发检查”设置,这样我们就可以开始使用不同级别的检查来检查代码了)。

无论如何,您可以使用一个参与者提供线程安全的交互,其值如下:

代码语言:javascript
复制
actor AnimalActor {
    var animal = "Dog"
    
    func setAnimal(newAnimal: String) {
        animal = newAnimal
    }
}

func testAsync() async {
    let animalActor = AnimalActor()
    
    Task {
        try await Task.sleep(nanoseconds: 2 * NSEC_PER_SEC)
        await animalActor.setAnimal(newAnimal: "Cat")
        print(await animalActor.animal)
    }

    print(await animalActor.animal)
}

Task {
    await testAsync()
}

有关更多信息,请参见WWDC 2021的用斯威夫特演员保护易变状态和2022年的使用Swift并发消除数据竞赛

注意,在上面,我避免使用GCD。asyncAfter是一种古老的GCD技术,用于在不阻塞当前线程的同时推迟某些工作。但是新的Task.sleep (与旧的Thread.sleep不同)在并发系统中实现了相同的行为(并提供取消功能)。在可能的情况下,我们应该避免Swift并发代码库中的GCD。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74372835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档