Go 的 Contex 是线程安全的吗?
前言
最近一个群里看到一个有趣的八股文,问题是:使用
context
携带的value
是线程安全的吗?这道题其实就是考察面试者对context
实现原理的理解,如果不知道context
的实现原理,很容易答错这道题,所以本文我们就借着这道题,再重新理解一遍context
携带value
的实现原理。
context
携带value
是线程安全的吗?
先说答案,context
本身就是线程安全的,所以context
携带value
也是线程安全的,写个简单例子验证一下:
func main() {ctx := context.WithValue(context.Background(), "asong", "test01")go func() {for {_ = context.WithValue(ctx, "asong", "test02")}}()go func() {for {_ = context.WithValue(ctx, "asong", "test03")}}()go func() {for {fmt.Println(ctx.Value("asong"))}}()go func() {for {fmt.Println(ctx.Value("asong"))}}()time.Sleep(10 * time.Second)
}
程序正常运行,没有任何问题,接下来我们就来看一下为什么context
是线程安全的!!!
为什么线程安全?
context
包提供两种创建根context
的方式:
context.Backgroud()
context.TODO()
又提供了四个函数基于父Context
衍生,其中使用WithValue
函数来衍生context
并携带数据,每次调用WithValue
函数都会基于当前context
衍生一个新的子context
,WithValue
内部主要就是调用valueCtx
类:
func WithValue(parent Context, key, val interface{}) Context {if parent == nil {panic("cannot create context from nil parent")}if key == nil {panic("nil key")}if !reflectlite.TypeOf(key).Comparable() {panic("key is not comparable")}return &valueCtx{parent, key, val}
}
valueCtx
结构如下:
type valueCtx struct {Contextkey, val interface{}
}
valueCtx
继承父Context
,这种是采用匿名接口的继承实现方式,key,val
用来存储携带的键值对。
通过上面的代码分析,可以看到添加键值对不是在原context
结构体上直接添加,而是以此context
作为父节点,重新创建一个新的valueCtx
子节点,将键值对添加在子节点上,由此形成一条context
链。
获取键值过程也是层层向上调用直到最终的根节点,中间要是找到了key
就会返回,否会就会找到最终的emptyCtx
返回nil
。画个图表示一下:
总结:context
添加的键值对一个链式的,会不断衍生新的context
,所以context
本身是不可变的,因此是线程安全的。
总结
本文主要是想带大家回顾一下context
的实现原理,面试中面试官都喜欢隐晦提出问题,所以这就需要我们有很扎实的基本功,一不小心就会掉入面试官的陷阱,要处处小心哦~
好啦,本文到这里就结束了,我们下期见。
Go 的 Contex 是线程安全的吗?相关推荐
- 多线程编程指南 part 2
多线程编程指南 Sun Microsystems, Inc. 4150 Network Circle Santa Clara, CA95054 U.S.A. 文件号码819–7051–10 2006 ...
- 并发编程-06线程安全性之可见性 (synchronized + volatile)
文章目录 线程安全性文章索引 脑图 可见性定义 导致不可见的原因 可见性 -synchronized (既保证原子性又保证可见性) 可见性 - volatile(但不保证操作的原子性) volatil ...
- win32 c语言创建线程,【原创】win32线程及线程内核对象
内核对象与GDI对象 GDI对象: 1. DC 2. 画笔 3. 画刷 内核对象 1. 进程 process 2. 线程 thread 3. 文件 file 4. 事件 envent 5. 信号量 s ...
- io_uring 触发内核线程的问题 iou-wrk 线程 io_uring 原理 io_uring SQPOLL 原理
(这里归档到胡思乱想就是不是作为容易查看的技术博客文章存在,给自己归档一下) 2022.04.07 io_uring 内部的实现是 poll(feat_fast_poll),线程池(iou-wrk-x ...
- java 手编线程池_死磕 java线程系列之自己动手写一个线程池
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...
- Redis 笔记(12)— 单线程架构(非阻塞 IO、多路复用)和多个异步线程
Redis 使用了单线程架构.非阻塞 I/O .多路复用模型来实现高性能的内存数据库服务.Redis 是单线程的.那么为什么说是单线程呢? Redis 在 Reactor 模型内开发了事件处理器,这个 ...
- Python 多线程总结(2)— 线程锁、线程池、线程数量、互斥锁、死锁、线程同步
主要介绍使用 threading 模块创建线程的 3 种方式,分别为: 创建 Thread 实例函数 创建 Thread 实例可调用的类对象 使用 Thread 派生子类的方式 多线程是提高效率的一种 ...
- 详解 Tomcat 的连接数与线程池
原文出处:编程迷思 前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文 ...
- Spring并发访问的线程安全性问题
下面的记录对spring中并发的总结.理论分析参考Spring中Singleton模式的线程安全,建议先看 spring中的并发访问题: 我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下 ...
最新文章
- 特斯拉“国王”王权不保
- 洪小文:以科学的方式赤裸裸地剖析AI(二)|从寒冬到复兴
- [C#]关于Access的“INSERT INTO 语句的语法错误”问题
- python提取字符串中的 中文 日文 韩文
- 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1099:第n小的质数
- python图片内容长度识别_Python实现识别图片内容的方法分析
- ODPS2.0重装上阵,优化提升SQL语言表达能力
- php 代码下载_PHP实现下载功能的代码
- php自动滚动到页尾,让DOM元素自动滚到视野内ScrollIntoView
- 浮动特性-脱标(HTML、CSS)
- python selenium page object_Selenium Page Object 自动化测试框架-Page Object设计
- 自定义 feign 调用实现 hystrix 超时、异常熔断
- uniapp 微信浏览器H5页面自定义分享链接
- 局域网文件传输方式分析
- 各代iphone尺寸_iPhone每一代的屏幕尺寸比例是多少?
- Linux下tftp服务器/客户端安装
- 对象数组中根据某个属性名的值相同,求某一项的和。
- WindowsPE无法安装系统
- ESXI自动关机 ping值检测关机脚本
- 信息熵、相对熵和交叉熵
热门文章
- 高可用之KeepAlived(2):keepalived+lvs
- Android 使用webview遇到的问题及解决办法
- 启动NASA“造导弹”,阿里为何要“上天”?
- memcached常用命令
- 证明randomized quicksort的平均running time为nlgn 的数学过程
- 为什么统计学家应该关注数据挖掘
- 利用权限禁止QQ的自动升级(QQUpdateCenter)
- (十五) 构建springmvc+mybatis+dubbo分布式平台-window安装dubbo管控台
- iOS 怎么设置 UITabBarController 的第n个item为第一响应者?
- 美团搜索-搜索引擎关键字智能提示的一种实现[转]