首页 > 其他分享 >关于golang线程安全

关于golang线程安全

时间:2023-04-26 13:13:04浏览次数:31  
标签:string golang 安全 线程 操作 赋值

最近在字节面试,面试有一个提问:


golang中的string赋值是线程安全的吗?如果是,怎么验证,如果不是,怎么验证

第一反应,golang的string底层结构:

type stringStruct struct {
    str unsafe.Pointer
    len int
}

其中 str 是一个不变数组,
所以该变字符串的内容都会重新生成一个底层数组,

但在字符串拼接,比如 1000个goroutine 进行字符串拼接操作,最终的结果并不一定是我们预期的,所以,golang string并不是线程安全的,这是我当时的回答。

现在看来,针对这个面试题,这个回答明显不正确,或许是答非所问,

  1. 我们所说的线程安全,是指操作,而不是指数据类型
  2. 假如某个操作在执行时,可以通过一条机器指令完成,那么它一定是线程安全的,因为这一条指令是一个原子操作
  3. 不可改变的数据与线程安全并没有关系,线程安全关注的是操作的安全性

比如,我们对某个变量的读操作,那么它一定是线程安全的,不管是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、字符串、复数型的类型的赋值都不是线程安全的

参考文档:https://www.cnblogs.com/sunsky303/p/17082018.html

 

标签:string,golang,安全,线程,操作,赋值
From: https://www.cnblogs.com/xiezhengcai/p/17355589.html

相关文章

  • 引用 maxmind golang 库导致的程序无法 recover crash 的问题
    新做的Gateway程序打算使用一个maxmind第三方库来解析地理信息,想了一下比较简单找了一个库直接使用。项目跑了一天得到了一堆panic,程序崩溃超过1s丢了不少数据。 从stack信息可以看到调用amxminddb-golang这个库的readLeft出现了错误,最后抛出了一个unexceptedf......
  • 线程使用例子
    点击查看代码packagecom.ly.fn.biz.ht.esign.expand.core.config;importcom.google.common.base.Joiner;importjava.math.BigDecimal;importjava.text.DecimalFormat;importjava.text.NumberFormat;importjava.text.ParseException;importjava.util.ArrayList;i......
  • golang 使用 net包实现 tcp server 示例
    之前用到golang进行网络编程时,主要就是使用net/http和web框架gin,这些网络库的底层其实也还是用的标准库自带的net包,很多是对路由或者其他做封装,而且golang本身的长处之一也是网络IO的处理,这也得益于其底层的IO模型,今天我们分享的是基于TCPserver/client的简单实现,后......
  • Golang - time包获取当前日期/时间戳并格式化输出
    获取时间对象packagemainimport("fmt""time")//24小时制constLAYOUT="2006-01-0215:04:05"//只能用这个日期,据说这是golang的诞生时间funcmain(){//获取当前日期now:=time.Now()fmt.Printf(now.Format(LAYOUT))//2022......
  • C++ 多线程并发
    C++参考手册-并发支持库《C++ConcurrencyinAction》https://segmentfault.com/a/1190000040628584?utm_source=sf-similar-articlehttps://zhuanlan.zhihu.com/p/547312117bilibiliC++多线程并发基础入门教程1创建线程C++11之前原生不支持多线程,C++11起逐步引......
  • Rust编程语言入门之最后的项目:多线程 Web 服务器
    最后的项目:多线程Web服务器构建多线程Web服务器在socket上监听TCP连接解析少量的HTTP请求创建一个合适的HTTP响应使用线程池改进服务器的吞吐量优雅的停机和清理注意:并不是最佳实践创建项目~/rust➜cargonewhelloCreatedbinary(application)`......
  • python线程池设计
    什么是线程池?诸如web服务器、数据库服务器、文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务。构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就创建一个新的服务对象,然后在新的服务对象中为请求服务。但当有大量请求并发访问时,服......
  • 智安网络 |关于《等保合规,保障信息安全》
    随着信息化发展,网络安全面临越来越多的威胁与挑战,为了确保信息安全,各国政府纷纷制定安全法规和政策。中国政府实施等保工作可以说是中国信息安全保障的一项重要措施。为进一步完善安全保障机制,促进信息化和网络安全的发展,国家互联网信息办公室出台了“网络安全等级保护(以下简称等......
  • 多线程-从os层面理解常见概念
    如何创建一个线程在Linux系统中有一个方法,他有四个参数,其中第一个参数是利用指针传入,后期如果被修改也会同步修改,第三个参数和自己定义的run方法有关,后面会详细说。intpthread_create(pthread_t*thread,constpthread_attr_t*attr,void*(*start_routine)(void*),vo......
  • golang 中通过strings/bytes/bufio 等包实现相关IO
    在go的IO中,除了io、os等包,我们还有strings、bytes、bufio等实现IO读写,这其中有些实现了io.Reader,有些同时实现了io.Reader和io.Writer接口。接下来我们一个个看相关的使用。1.strings在strings包中,只实现了Reader,我们看看其代码://实现的readertypeRea......