Swift值类型线程安全疑问:异步函数局部变量修改问题
关于Swift异步函数中值类型局部变量的疑问解答
首先直接给结论:你修改的是同一个myStruct变量对应的实例,后台线程并没有创建独立的新实例,最终print会输出Goodbye, World!。
核心原因解析:
- Swift的
async/await采用挂起-恢复的执行模型,而非为每个线程复制函数栈。当执行到await时,当前函数的执行状态(包括所有局部变量的当前值)会被保存,等Task.sleep完成后,系统会在某个可用线程(可能是后台线程)恢复函数执行,此时操作的还是原来的局部变量。 - 对于值类型
MyStruct,变量myStruct直接存储实例本身。主线程创建第一个MyStruct(text: "Hello, World!")实例后,await挂起时这个值被保存;恢复到后台线程后,myStruct = MyStruct(text: "Goodbye, World!")是给同一个变量赋值新实例,覆盖了原来的值。 - 你提到的“每个线程有独立栈”是事实,但异步函数的局部变量不会绑定在某个线程的栈上。Swift会把异步函数的状态(包括局部变量)在挂起时转移到堆上的任务上下文里,恢复时再加载到当前线程的栈中执行,所以不管切换到哪个线程,操作的都是同一个变量的状态。
额外补充:
这种异步执行模式下,值类型的线程安全性依然成立——因为await的挂起和恢复是串行的,不会出现多个线程同时操作同一个myStruct变量的情况,自然不会有数据竞争问题。
内容的提问来源于stack exchange,提问作者zfgo
相关产品推荐
相关产品推荐

