栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

原文地址: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上进行。

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

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

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/642946.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号