解决 Swift 6 全局变量不能满足并发安全(concurrency-safe)读写的问题

在这里插入图片描述

概述

WWDC 24 终于在 Swift 十岁生日发布了全新的 Swift 6。这不仅意味着 Swift 进入了全新的“大”版本时代,而且 Swift 编译器终于做到了并发代码执行的“绝对安全”。

在这里插入图片描述

不过,从 Swift 5 一步迈入“新时代”的小伙伴们可能对新的并发检查有些许“水土不服”,比如在同步全局变量时可能会引发 Swift 6 编译器的“怨声载道”。

在本篇博文中,您将学到如下内容:

  • 概述
  • 1. 由一个并发错误引发的“探险”
  • 2. 拯救者:全局 Actor!
  • 3. 另一种解决之道
  • 总结

驯服 Swift 6 并发代码执行中的安全隐患是每个秃头码农心中的“壮志凌云”,那还等什么呢?让我们马上将“野性难驯”的 Concurrency 执行驯化的俯首帖耳吧!

Let‘s go!!!😉


1. 由一个并发错误引发的“探险”

在将 Xcode 项目的编译器版本从 Swift 5 升级至 6 之后,小伙伴们会发之前很多“安适如常”的并发代码突然变得东差西误起来。
在这里插入图片描述

比如,下面一段简单的代码在 Swift 6 环境中运行就仿佛会“魂不守舍”一般:

var id = UUID()func test() async {id = UUID()
}

除了全局变量以外,对于结构或类的静态变量也会有类似的问题:

struct Model {static var id = UUID()func test() async {id = UUID()}
}

在这里插入图片描述

这都是怎么回事呢?

在这里插入图片描述

原来,从 Swift 6 开始苹果对并发执行安全性的态度变得极度较真起来。为了不惯着 Swift 5 中模棱两可的并发错误,苹果采取“零容忍”策略让代码中所有潜在的并发陷阱都变得“原形毕露”了!

在这里插入图片描述

在上面的代码中,我们在异步 test 方法中修改了全局变量,而该方法有可能会被并发执行。这绝对是一个非常严重的并发同步错误。除了将全局变量 id 变为只读(在这个例子中显然不可行)以外,还有其它解决良策么?

答案是:必须的!

2. 拯救者:全局 Actor!

为了让全局变量不受并发执行同步的困扰之苦,我们可以简单的将它们用 MainActor 来修饰:

@MainActor
var id = UUID()@MainActor
func test() async {id = UUID()
}

不过这样一来,我们就必须把所有涉及全局变量的读写操作都限制在主线程上,这无疑加重了主线程中不必要的执行负担。

然而,我们可以创建自己的全局 Actor ,然后用这些自定义全局 Actor 来让之前的同步问题迎刃而解:

@globalActor
actor MyActor {static let shared = MyActor()
}@MyActor
var id = UUID()@MyActor
func test() async {id = UUID()
}@MyActor
struct Model {static var id = UUID()func test() async {Self.id = UUID()}
}

或者不用全局 Actor 来修饰 test 方法,而在 test 内部做文章:

func test() async {Task {@MyActor inid = UUID()}
}

这样一来,我们就可以将所有对全局变量的读写限制在特定的 Actor 之中,从而大功告成!


更多关于 Swift 语言中 Actor 的更多介绍,请小伙伴们移步如下链接进一步观赏精彩内容:

  • Swift 结构化并发之全局 Actor 趣谈
  • 深入理解 Swift 新并发模型中 Actor 的重入(Reentrancy)问题
  • SwiftUI async/await 并发代码提示 Non-sendable type cannot cross actor boundary 警告的解决

3. 另一种解决之道

除了用上面的方法以外,如果可以确定对全局变量的并发读写绝对不会引发同步问题的话,我们还可以显式让编译器“明明白白我们的心”:

nonisolated(unsafe)
var id = UUID()func test() async {id = UUID()
}

如上代码所示:我们用 nonisolated(unsafe) 修饰语句明确告知 Swift 6 编译器,id 全局变量绝对不会导致并发执行中的同步问题。但这样一来,编译器将会对该全局变量在同步执行中所有的并发潜在问题置之不理、一笑而过。所以,这等于将全部的并发安全检查又重新转移到了小伙伴们自身的肩头。

使用 nonisolated(unsafe) 修饰语句还有一种可能是:明知这些全局变量可能发生并发同步问题,但暂时先将他们搁置一边,等以后再集中火力攻克它们。

希望大家在使用这种方法时慎之又慎,切记切记!


想要系统学习 Swift 的小伙伴们,可以移步我的《Swift 语言开发精讲》专栏来看一看哦:

在这里插入图片描述

  • Swift 语言开发精讲

总结

在本篇博文中,我们讨论了在 Swift 6 中异步并发读写全局变量时让编译器“大发雷霆”的原因,并给出多种解决之道,棒棒哒!

感谢观赏,再会啦!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/404089.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

迭代器失效

一、什么是迭代器失效 迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器底层对应指针所指…

使用Virtio Driver实现一个计算阶乘的小程序——QEMU平台

目录 一、概述 二、代码部分 1、Virtio 前端 (1) User Space (2) Kernel Space 2、Virtio 后端 三、运行 QEMU Version:qemu-7.2.0 Linux Version:linux-5.4.239 一、概述 本篇文章的主要内容是使用Virtio前后端数据传输的机制实现一个计算阶乘的…

【RabbitMQ】 相关概念 + 工作模式

本文将介绍一些MQ中常见的概念,同时也会简单实现一下RabbitMQ的工作流程。 MQ概念 Message Queue消息队列。是用来存储消息的队列,多用于分布式系统之间的通信。 系统间调用通常有:同步通信和异步通信。MQ就是在异步通信的时候使用的。 同…

萝卜快跑和端到端的自动驾驶(1)

先看一篇论文 2311.18636 (arxiv.org) 这篇论文里有一个非常好的图 比较了一下模块化任务(级联任务)和端到端自动驾驶的区别 首先什么叫模块化任务(级联) 如上图所示,左边的方块中的子方块,是展示了自动驾驶获取数据的途径,这里包括&…

Java之文件操作和IO

目录 File类 属性 构造方法 方法 文件内容的读写 InputStream OutputStream File类 属性 修饰符及类型属性说明static StringpathSeparator依赖于系统的路径分隔符,String类型的表示static charpathSeparator依赖于系统的路径分隔符,char类型的…

vscode 远程免密登录

Windows R 输入 cmd在命令行终端中输入 ssh-keygen 一直回车、确定 生成秘钥 3. C:\用户\xxx.ssh 拷贝公钥内容 id_rsa.pub 4. 在虚拟机~/.ssh/ 下创建文件touch authorized_keys,拷贝公钥内容 id_rsa.pub粘贴到authorized_keys里即可。

uniapp自定义请求头信息header

添加请求头:uniapp自定义请求头信息header,如下:添加tenant-id参数 代码

信创教育:培养未来科技创新的生力军

随着全球数字化转型的加速,信息技术应用创新(简称“信创”)产业作为推动国家信息技术自主可控和产业升级的关键领域,正迎来前所未有的发展机遇。信创教育,作为培养未来科技创新生力军的重要阵地,其重要性和…

win的netassist TCP测试工具和Linux的nc工具使用

写在前面 有时工作中我们编写一些tcp相关的程序,而netassist就是这样一款辅助我们进行TCP功能测试的工具,你可以从这里下载。 1:netassist使用 我们需要一个server程序,可以参考这篇文章,启动server后,就…

系列:水果甜度个人手持设备检测-产品规划的方案和实现思路

系列:水果甜度个人手持设备检测 -- 产品规划的方案和实现思路 背景 我们在前面篇章中,大致的检索了一下市面存在的产品,并采用启发性搜索的办法从国家知识产权局的专利库、中国知网CNKI的学术文献库、各种文章、论坛甚至是GitHub中对我们预研的方向进…

EmguCV学习笔记 VB.Net 2.S 特别示例

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 教程VB.net版本请访问:EmguCV学习笔记 VB.Net 目录-CSDN博客 教程C#版本请访问:EmguCV学习笔记 C# 目录-CSD…

【区块链+金融服务】中国银联区块链可信存证服务 | FISCO BCOS应用案例

随着金融行业信息化的快速推进,“互联网 金融”业务产生了海量的电子数据。例如,截止到 2022 年第二季度, 全国累计信用卡发卡数量约 8.07 亿张,累计银行卡应偿信贷余额为 8.66 万亿元,累计信用卡逾期半年未尝信贷 总…

盲盒抽奖源码

介绍: 功能上还可以,商品和盲盒可以在你程序里添加,设置概率等!! 新盲盒星球抽奖商城手机网站源码 随机开箱抢购 代码有点大,三百多M。 教程搭建很简单,基本10分钟搭建一套,可一个服务器搭建多套,只要你…

云计算实训31——playbook(剧本)基本应用、playbook常见语法、playbook和ansible操作的编排

playbook(剧本): 是ansible⽤于配置,部署,和管理被控节点的剧本。⽤ 于ansible操作的编排。 使⽤的格式为yaml格式 一、YMAL格式 以.yaml或.yml结尾 ⽂件的第⼀⾏以 "---"开始,表明YMAL⽂件的开始(可选的) 以#号开头为注释 列表中的所有成员都开始于…

不能使用乘除法、for、while、if、else、switch、case求1+2+3+...+n

求123...n_牛客题霸_牛客网 (nowcoder.com) 描述 求123...n&#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句&#xff08;A?B:C&#xff09;。 数据范围&#xff1a; 0<n≤2000<n≤200 进阶&#xff1a; 空间复杂度 O(1)O(…

深度相机与红外光相机+摄像头RTSP协议

0、绪论 一般而言&#xff0c;从深度信息的角度考虑相机&#xff0c;相机可以分为&#xff1a;单目&#xff0c;双目&#xff0c;RGB-D相机&#xff1b;单目或者双目相机都是通过被动的接收信息之后通过算法解算得到图片中的深度信息&#xff0c;​ RGB-D相机是主动式的&#…

本地私有化部署PDF处理神器Stirling PDF并实现无公网IP远程在线访问

文章目录 前言1. 安装Docker2. 本地安装部署StirlingPDF3. Stirling-PDF功能介绍4. 安装cpolar内网穿透5. 固定Stirling-PDF公网地址 前言 本篇文章我们将在Linux上使用Docker在本地部署一个开源的PDF工具——Stirling PDF&#xff0c;并且结合cpolar的内网穿透实现公网随时随…

通过共享目录上传后门

本文来自无问社区&#xff0c;更多实战内容可前往查看http://www.wwlib.cn/index.php/artread/artid/13337.html 操作步骤 枚举目标主机开启的共享服务信息&#xff1a;10.0.0.6 smbclient -L //10.0.0.6 -U spotWARNING: The "syslog" option is deprecated Ente…

【数据结构】关于Java对象比较,以及优先级队列的大小堆创建你了解多少???

前言&#xff1a; &#x1f31f;&#x1f31f;Hello家人们&#xff0c;这期讲解对象的比较&#xff0c;以及优先级队列堆&#xff0c;希望你能帮到屏幕前的你。 &#x1f308;上期博客在这里&#xff1a;http://t.csdnimg.cn/MSex7 &#x1f308;感兴趣的小伙伴看一看小编主页&…

LeetCode --- 410周赛

题目列表 3248. 矩阵中的蛇 3249. 统计好节点的数目 3250. 单调数组对的数目 I 3251. 单调数组对的数目 II 一、矩阵中的蛇 只要按照题目要求模拟即可&#xff0c;代码如下 class Solution { public:int finalPositionOfSnake(int n, vector<string>& commands…