Go面试看这里了~(十四)

161 篇文章 12 订阅

原文地址:Go面试看这里了~(十四)

1、main和init的区别?

main和init的相同点:定义时不能有任何参数或返回值,且Go程序自动调用。

main和init的不同点:

  1. init可应用于任意包中,且可重复定义多个。

  2. main只能用于main包中,且只能定义一个。

main和init的执行顺序:

  1. 对同一Go文件的init调用顺序是从上到下。

  2. 对同一package中不同文件的init是按文件名称字符串大小从小到大顺序调用。

  3. 对不同package,如不相互依赖,则按main中先import后调用顺序调用init。

  4. 对不同package,如相互依赖,则先调用最早被依赖的package的init。

2、什么情况下Go runtime会创建一个协程?

在Go程序中可能有数千Go协程运行在一个线程中,如该线程中任一Go协程阻塞(如等待用户输入),此时Go会创建一个新OS线程并将其余Go协程移动到此线程,以上操作都是runtime来完成。

3、原生map线程安全吗?为什么?怎么实现线程安全map操作?

原生map线程不安全,在同一时间段内,不同goroutine对同一字典读写,其本身可能会因这些操作而产生混乱,相关程序也可能会因此出现不可预知的问题。

Go sync包提供线程安全的map,主要还是配合(锁)实现线程安全的map,主要实现方式有以下几种:

  1. 悲观锁:进来的每一步操作都认为同时会有其他进程影响操作,所以提前加锁。

  2. 乐观锁:因为map线程不安全的,可能是因为读-写或写-写造成的,所以在map写的时候加上锁就会提高map的性能。

  3. 根据map实现原理,在buckets或map更基本的组成层面加锁,根据乐观锁的情况进行小范围加锁。

sync.Map的实现原理可概括为以下几点:

  1. 通过read和dirty两字段将读写分离,读的数据存在只读字段read上,将最新写入的数据存在dirty字段上。

  2. 读取时会先查询read,不存在再查询dirty,写入时则只写入dirty。

  3. 读取read并不需要加锁,而读或写dirty都需要加锁。

  4. 使用misses字段统计read被穿透的次数(被穿透指需要读dirty的情况),超过一定次数则将dirty数据同步到read上。

  5. 删除数据直接通过标记来延迟删除。

来看下sync.Map的使用案例:

  var ma sync.Map                // 只需要声明即可使用
  ma.Store("key", "value")       // 存储值
  ma.Delete("key")               // 删除值
  ma.LoadOrStore("key", "value") // 获取值,如果没有则存储
  fmt.Println(ma.Load("key"))    // 获取值

  ma.Range(func(key, value interface{}) bool { // 遍历
    fmt.Printf("key:%s ,value:%s \n", key, value)
    return true // return一个true,继续执行,return一个false直接退出循环
  })

map底层写的很棒,但为了效率,并未实现线程安全,所以另外加了sync.map,兼容线程安全,sync.map实现是依靠两张map对读操作和写操作分离,后续根据需要将dirty map合入read map中,相对于乐观锁实现的方式,写进程执行的时候,读进程也可能在read map上进行。

至此,本次分享就结束了,后期会慢慢补充。

以上仅为个人观点,不一定准确,能帮到各位那是最好的。

好啦,到这里本文就结束了,喜欢的话就来个三连击吧。

扫码关注公众号,获取更多优质内容。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值