关于golang线程安全
golang中的string赋值是线程安全的吗?
第一反应,golang的string底层结构:
type stringStruct struct {
str unsafe.Pointer
len int
}
其中 str 是一个不变数组,
现在看来,针对这个问题,需要清楚:
- 我们所说的线程安全,是指操作,而不是指数据类型
- 假如某个操作在执行时,可以通过一条机器指令完成,那么它一定是线程安全的,因为这一条指令是一个原子操作
- 不可改变的数据与线程安全并没有关系,线程安全关注的是操作的安全性
比如,我们对某个变量的读操作,那么它一定是线程安全的,不管是map、sync.map、string、int,这个读操作都是线程安全的。
假如我们对一个 var int i = 10 做自增操作 i++,那么,这个操作就不是并发安全的,因为i++ 在机器指令上可以分为:读取i的值,对i的值做加1操作,这两个操作之间,很明显,会被中断,在多个线程操作的时候,会产生非预期的结果。
所以,面试题中的提问是指golang 中的string类型做 “赋值” 这个操作的时候,是线程安全的吗?
我们先抛开这个问题,考虑一个通用的场景,结构体类型的赋值是线程安全的吗?
比如一个结构体:
type S struct {
b int
a int
}
var v = S{a:1,b:2}
v = S{a:3,b:4}
上面中对变量中v的赋值操作,可分为对字段a的赋值,然后再对b的赋值,这是两个机器指令,所以,如果在两个并发的线程中操作,并不是线程安全的,那么,当结构体中只有一个字段,是否是线程安全的呢?答案是:线程安全的。
同样,假如你只修改结构体中的一个字段,其也是线程安全的,比如你只修改上面的结构体中的a字段,那么是线程安全的。
所以,同样的,对string的 赋值操作,也不是线程安全的,它与string的底层数组是否是不变数组没有关系。
延伸一下,那哪些类型在golang中赋值是线程安全的呢:
字节型、布尔型、整型、浮点型、字符型
以上这些类型的赋值都可以在一条机器指令完成,这儿特别说明一下,以int64位而言,如果在32位的机器上赋值,那么一条指令并不能完成,所以也是不安全的。
另外,指针类型,函数类型的赋值也是线程安全的。
以下类型的赋值不是线程安全的:
数组、切片、字典、通道、接口、sync.map、字符串、复数型的类型的赋值都不是线程安全的
posted on 2023-04-26 12:56 xiezhengcai 阅读(709) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具