字节跳动Go 语言面试会问哪些问题?
1、Mutex 几种状态
mutexLocked — 表示互斥锁的锁定状态;
mutexWoken — 表示从正常模式被从唤醒;
mutexStarving — 当前的互斥锁进入饥饿状态;
waitersCount — 当前互斥锁上等待的 Goroutine 个数;
2、Mutex 正常模式和饥饿模式正常模式(非公平锁)
正常模式下,所有等待锁的 goroutine 按照 FIFO(先进先出)顺序等待。唤醒的goroutine 不会直接拥有锁,而是会和新请求锁的 goroutine 竞争锁的拥有。新请求锁的 goroutine 具有优势:它正在 CPU 上执行,而且可能有好几个,所 以刚刚唤醒的 goroutine 有很大可能在锁竞争中失败。在这种情况下,这个被 唤醒的 goroutine 会加入到等待队列的前面。如果一个等待的 goroutine 超过1ms 没有获取锁,那么它将会把锁转变为饥饿模式。
饥饿模式(公平锁)
为了解决了等待 G 队列的长尾问题
饥饿模式下,直接由 unlock 把锁交给等待队列中排在第一位的 G(队头),同 时,饥饿模式下,新进来的 G 不会参与抢锁也不会进入自旋状态,会直接进入 等待队列的尾部,这样很好的解决了老的 g 一直抢不到锁的场景。饥饿模式的触发条件,当一个 G 等待锁时间超过 1 毫秒时,或者当前队列只剩 下一个 g 的时候,Mutex 切换到饥饿模式。
总结
对于两种模式,正常模式下的性能是最好的,goroutine 可以连续多次获取 锁,饥饿模式解决了取锁公平的问题,但是性能会下降,其实是性能和公平的 一个平衡模式。
3、Mutex 允许自旋的条件
1 锁已被占用,并且锁不处于饥饿模式。
2 积累的自旋次数小于最大自旋次数(active_spin=4)。3 cpu 核数大于 1。
4 有空闲的 P。
5 当前 goroutine 所挂载的 P 下,本地待运行队列为空。
4、RWMutex 实现
通过记录 readerCount 读锁的数量来进行控制,当有一个写锁的时候,会将读 锁数量设置为负数 1<<30。目的是让新进入的读锁等待写锁之后释放通知读 锁。同样的写锁也会等等待之前的读锁都释放完毕,才会开始进行后续的操 作。而等写锁释放完之后,会将值重新加上 1<<30, 并通知刚才新进入的读锁(rw.readerSem),两者互相限制。
5、RWMutex 注意事项
RWMutex 是单写多读锁,该锁可以加多个读锁或者一个写锁
读锁占用的情况下会阻止写,不会阻止读,多个goroutine 可以同时获取读锁
写锁会阻止其他 goroutine(无论读和写)进来,整个锁由该 goroutine独占
适用于读多写少的场景
RWMutex 类型变量的零值是一个未锁定状态的互斥锁。
RWMutex 在首次被使用之后就不能再被拷贝。
RWMutex 的读锁或写锁在未锁定状态,解锁操作都会引发 panic。
RWMutex 的一个写锁 Lock 去锁定临界区的共享资源,如果临界区的共享资源已被(读锁或写锁)锁定,这个写锁操作的 goroutine 将被阻塞直到解锁。
RWMutex 的读锁不要用于递归调用,比较容易产生死锁。
RWMutex 的锁定状态与特定的 goroutine 没有关联。一个 goroutine 可以 RLock(Lock),另一个 goroutine 可以 RUnlock(Unlock)。
写锁被解锁后,所有因操作锁定读锁而被阻塞的 goroutine 会被唤醒,并都可以成功锁定读锁。
读锁被解锁后,在没有被其他读锁锁定的前提下,所有因操作锁定写锁而被阻塞的 goroutine,其中等待时间最长的一个 goroutine 会被唤醒。
6、Cond 是什么
Cond 实现了一种条件变量,可以使用在多个 Reader 等待共享资源 ready 的场 景(如果只有一读一写,一个锁或者 channel 就搞定了)
每个 Cond 都会关联一个 Lock(*sync.Mutex or *sync.RWMutex),当修改条 件或者调用 Wait 方法时,必须加锁,保护 condition。
7、Broadcast 和 Signal 区别
func (c *Cond) Broadcast()
Broadcast 会唤醒所有等待 c 的 goroutine。
调用 Broadcast 的时候,可以加锁,也可以不加锁。
func (c *Cond) Signal()
Signal 只唤醒 1 个等待 c 的 goroutine。
调用 Signal 的时候,可以加锁,也可以不加锁。
8、Cond 中 Wait 使用
func (c *Cond) Wait()
Wait()会自动释放 c.L,并挂起调用者的 goroutine。之后恢复执行,Wait()会 在返回时对 c.L 加锁。
除非被 Signal 或者 Broadcast 唤醒,否则 Wait()不会返回。
由于 Wait()第一次恢复时,C.L 并没有加锁,所以当 Wait 返回时,调用者通常 并不能假设条件为真。
取而代之的是, 调用者应该在循环中调用 Wait。(简单来说,只要想使用condition,就必须加锁。)
for !condition() {c.Wait()
}
... make use of condition ...
c.L.Unlock()
c.L.Lock()
9、WaitGroup 用法
一个 WaitGroup 对象可以等待一组协程结束。使用方法是:
1. main 协程通过调用 wg.Add(delta int) 设置 worker 协程的个数,然后创 建 worker 协程;
2.worker 协程执行结束以后,都要调用 wg.Done();
3.main 协程调用 wg.Wait() 且被 block,直到所有 worker 协程全部执行结束 后返回。
10、WaitGroup 实现原理
WaitGroup 主要维护了 2 个计数器,一个是请求计数器 v,一个是等待计数 器 w,二者组成一个 64bit 的值,请求计数器占高 32bit,等待计数器占低32bit。
每次Add执行,请求计数器v加1,Done方法执行,请求计数器减1,v为0 时通过信号量唤醒 Wait()。
11、什么是 sync.Once
Once 可以用来执行且仅仅执行一次动作,常常用于单例对象的初始化场 景。
Once 常常用来初始化单例资源,或者并发访问只需初始化一次的共享资 源,或者在测试的时候初始化一次测试资源。
sync.Once 只暴露了一个方法 Do,你可以多次调用 Do 方法,但是只有第 一次调用 Do 方法时 f 参数才会执行,这里的 f 是一个无参数无返回值 的函数。
12、什么操作叫做原子操作
一个或者多个操作在 CPU 执行过程中不被中断的特性,称为原子性(atomicity)。这些操作对外表现成一个不可分割的整体,他们要么都执行,要 么都不执行,外界不会看到他们只执行到一半的状态。而在现实世界中,CPU不可能不中断的执行一系列操作,但如果我们在执行多个操作时,能让他们的 中间状态对外不可见,那我们就可以宣城他们拥有了“不可分割”的原子性。
在 Go 中,一条普通的赋值语句其实不是一个原子操作。列如,在 32 位机器上 写 int64 类型的变量就会有中间状态,因为他会被拆成两次写操作(MOV)——写 低32位和写高32位。
13、原子操作和锁的区别
原子操作由底层硬件支持,而锁则由操作系统的调度器实现。锁应当用来保护 一段逻辑,对于一个变量更新的保护,原子操作通常会更有效率,并且更能利 用计算机多核的优势,如果要更新的是一个复合对象,则应当使用atomic.Value 封装好的实现。
14、什么是 CAS
CAS 的全称为 Compare And Swap,直译就是比较交换。是一条 CPU 的原子指 令,其作用是让 CPU 先进行比较两个值是否相等,然后原子地更新某个位置的 值,其实现方式是给予硬件平台的汇编指令,在 intel 的 CPU 中,使用的cmpxchg 指令,就是说 CAS 是靠硬件实现的,从而在硬件层面提升效率。
简述过程是这样:
假设包含 3 个参数内存位置(V)、预期原值(A)和新值(B)。V 表示要更新变量的 值,E 表示预期值,N 表示新值。仅当 V 值等于 E 值时,才会将 V 的值设为 N, 如果 V 值和 E 值不同,则说明已经有其他线程在做更新,则当前线程什么都不 做,最后 CAS 返回当前 V 的真实值。CAS 操作时抱着乐观的态度进行的,它总 是认为自己可以成功完成操作。基于这样的原理,CAS 操作即使没有锁,也可 以发现其他线程对于当前线程的干扰。
15、sync.Pool 有什么用
对于很多需要重复分配、回收内存的地方,sync.Pool 是一个很好的选择。频 繁地分配、回收内存会给 GC 带来一定的负担,严重的时候会引起 CPU 的毛 刺,而 sync.Pool 可以将暂时不用的对象缓存起来,待下次需要的时候直接 使用,不用再次经过内存分配,复用对象的内存,减轻 GC 的压力,提升系统 的性能。
最后:
点击下方名片链接,关注 「码农编程进阶笔记 」微信公众号,在微信聊天对话框回复「go语言实战」「goweb编程」或者直接长按左下图海报中的二维码,可获取最新golang电子书和视频资源
字节跳动Go 语言面试会问哪些问题?相关推荐
- 面试字节跳动,被面试官的源码问题问到怀疑人生
面试字节跳动,被面试官的源码问题问到怀疑人生 最近,我的一位朋友在找工作,已经拿到了美团.快手等公司的Offer,准备选择其中一家入职了. 后来他又接到了字节跳动的电话,通知他去参加三面.从二面到三面 ...
- (99)利用任务task实现单字节乘法功能,面试必问(二十三)(第20天)
(99)利用任务task实现单字节乘法功能,面试必问(二十三)(第20天) 1 文章目录 1)文章目录 2)FPGA初级课程介绍 3)FPGA初级课程架构 4)利用任务task实现单字节乘法功能,面试 ...
- (98)利用函数function实现半字节加法功能,面试必问(二十二)(第20天)
(98)利用函数function实现半字节加法功能,面试必问(二十二)(第20天) 1 文章目录 1)文章目录 2)FPGA初级课程介绍 3)FPGA初级课程架构 4)利用函数function实现半字 ...
- 为什么字节跳动的前端面试需要那么难的算法题?
首先我来辟个谣: 随便打开一个招聘网站,你会发现前端工程师的岗位需求依旧庞大,大厂人才奇缺,就业薪资起点高,无行业限制. (数据来源:职友集) 前端开发的行业大环境 行业升级,如果说以前只会HTML. ...
- 【本人秃顶程序员】作为字节跳动的研发面试官,有些话我不得不说!
今天看到了一篇关于如何准备面试的文章,分享给大家.尽管很多人都讨厌 "面试造航母,工作螺丝钉"的局面,但又不得不收起脾气假笑面对.谁让谁僧多粥少呢? 正文开始 2019春招过半,面 ...
- 字节跳动Java后端面试真题,看完你学会了吗,「附面试福利」
前言; 之前有好多朋友给我留言说想去字节跳动,今天就给大家分享几道字节跳动的面试真题给大家,文末有福利哦. 一. 谈谈你对Java平台的理解? "Java 是解释执行",这句话正确 ...
- 4月跳槽进字节跳动了,面试真简单...
前言: 最近金三银四跳槽季,相信很多小伙伴都在面试找工作, 怎样才能拿到大厂的offer,没有掌握绝对的技术,那么就要不断的学习,没有绝对的天才,只有持续不断的付出.对于我们每一个平凡人来说,改变命运 ...
- 2021年字节跳动+京东+美团面试总结!专题解析
前言 很多人聊起移动端适配都是懵逼状态,都想口吐芬芳.难道移动端还要适配,直接px写死,其他自适应不就完了吗?其实不然,要求严格的公司会要求缩放比例完全相同,简单说就是,在每个手机上的每一行的字数都要 ...
- 字节跳动Android实习面试凉凉经,震撼来袭免费下载!
开头 最近,程序员这个圈子可谓热闹非凡,前不久,一个神奇的开源项目996.ICU诞生,几天时间就有超过10w+ star 和 1w+ fork ,可谓是Github上star增长最快的项目.996.i ...
最新文章
- gdal java shp_【GDAL/OGR】利用GDAL/OGR读取shp文件并转换为json文件(Java版)
- Linux vsftp服务
- as3 访问远程计算机,Flash AS3中数据发送与接收
- Redis性能问题排查解决手册(值得收藏)
- 程序图片运行效果存在偏差问题
- (王道408考研操作系统)第四章文件管理-第二节3:减少延迟时间的方法
- 两个for做数据插入_冒泡排序、选择排序、插入排序
- 容器入门(8) - 镜像签名
- 小程序进阶学习02--安装webstorm
- 九度oj 题目1028:继续畅通工程
- 开源hr系统 java_微人事-前后端分离的人力资源管理系统-江南一点雨
- Win10系统隐藏磁盘
- html简介百度百科,outerHTML
- uboot_v2016 版本中fw_printenv的编译问题
- 【ROM制作工具】华为UPDATE.APP固件一键解包打包教程
- CSS画出半圆,四分之一圆,三角等图形
- apicloud打开地图导航
- SQL SERVER 连乘写法
- android handler的机制和原理_Android完整知识体系路线(菜鸟-资深-大牛必进之路)
- 二值图像blob分析