1 选择go的原因?
- 简单性
Go语言的语法简洁清晰,没有过多的封装和继承机制,学习和使用门槛较低。 - 高并发
Go语言从语言层面原生支持并发,通过goroutine和channel实现并发编程,比如Web服务器可以轻松处理大量并发连接。 - 高性能
Go程序接近机器码运行,甚至有些情况下性能可以与C程序相媻,而开发效率又高于C/C++。GC(垃圾回收)简单高效。 - 静态链接
Go编译后生成的是单个静态链接的二进制文件,方便部署,跨平台也更简单。 - 标准库
Go语言自带了很多强大的标准库,网络编程、并发编程、编码解码等功能一应俱全。
与Java相比,Go语言的性能更出色,对并发支持更好。同时Go没有像Java那样庞大的类库和复杂的语法,更注重语法的简洁和可读性。
但Java在企业级应用、成熟的框架和庞大的资源库上仍占有优势,生态更为完善。
总的来说,Go语言更适合编写底层系统编程、分布式系统、网络编程等对性能和并发性有较高要求的领域。
2 带GC的语言都有哪些,说一下Go语言的GC
有GC(垃圾回收)的编程语言有很多,比如Java、C#、Python、Ruby、Go等。其中比较流行和常用的语言有:
- Java
- C#
- Go
- Python
- Node.js(JavaScript)
- Ruby
- Scala
- Rust
Go的GC
变革
- Go V1.3的标记-清除(mark and sweep)法。
- Go V1.5的三色并发标记法。
- Go V1.5的强三色不变式、弱三色不变式、插入屏障、删除屏障。
- Go V1.8的混合写屏障机制。
Go语言使用了三色标记清除(Tri-Color Mark Sweep)算法进行垃圾回收。这是一种增量式的并发GC算法。
Go V1.5的三色并发标记法, 主要流程是:
- 启动STW
- 新创建的对象默认颜色是白色
- GC回收从根节点一次遍历所有对象,把遍历到的对象从白色集合放入灰色集合。
- 循环遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,之后将此灰色对象放入黑色集合,直到灰色中无任何对象
- 停止STW
- 回收所有的白色标记表的对象.也就是回收垃圾。
强三色不变式和弱三色不变式。
在三色标记法的过程中对象丢失,需要同时满足下面两个条件:
条件一:白色对象被黑色对象引用
强三色不变式
规则:不允许黑色对象引用白色对象
条件二:灰色对象与白色对象之间的可达关系遭到破坏
弱三色不变式
规则:黑色对象可以引用白色对象,但是白色对象的上游必须存在灰色对象
实现机制:插入写屏障和删除写屏障。
插入写屏障:
规则:当一个对象引用另外一个对象时,将另外一个对象标记为灰色。
满足:强三色不变式。不会存在黑色对象引用白色对象
插入屏障仅会在堆内存中生效,不对栈内存空间生效,这是因为go在并发运行时,大部分的操作都发生在栈上,函数调用会非常频繁。
删除写屏障
规则:在删除引用时,如果被删除引用的对象自身为灰色或者白色,那么被标记为灰色。
满足弱三色不变式。灰色对象到白色对象的路径不会断
对比插入写屏障和删除写屏障:
- 插入写屏障:
- 插入写屏障哪里都好,就是栈上的操作管不到,所以最后需要对栈空间进行stw保护,然后rescan保证引用的白色对象存活。
- 删除写屏障:
- 在GC开始时,会扫描记录整个栈做快照,从而在删除操作时,可以拦截操作,将白色对象置为灰色对象。
- 回收精度低。
Go V1.8的混合写屏障机制。
混合写屏障的具体核心规则如下:
- GC开始将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW),
- GC期间,任何在栈上创建的新对象,均为黑色。
- 被删除的对象标记为灰色。
- 被添加的对象标记为灰色。
GoV1.8三色标记法加混合写屏障机制,栈空间不启动屏障机制,堆空间启动屏障机制。整个过程几乎不需要STW,效率较高。
Go的GC有如下一些特点:
- 并发的增量式GC,与应用程序并发运行
- 对CPU开销控制良好,在20%以内
- 自动调整GOGC值来控制内存占用
- 避免在系统压力大时启动GC以防停顿时间过长
- 避免内存碎片
总结
- Golang v1.3之前采用传统采取标记-清除法,需要STW,暂停整个程序的运行。
- 在v1.5版本中,引入了三色标记法和插入写屏障机制,其中插入写屏障机制只在堆内存中生效。但在标记过程中,最后需要对栈进行STW。
- 在v1.8版本中结合删除写屏障机制,推出了混合屏障机制,屏障限制只在堆内存中生效。避免了最后节点对栈进行STW的问题,提升了GC效率
标签:专题,并发,对象,标记,面试,屏障,GC,Go From: https://www.cnblogs.com/wise-mushroom/p/18220879总的来说,Go语言的GC算法在简单性、开销和用户体验等方面做了很好的权衡和优化。这也是Go适合编写高并发、对延时敏感的系统的一个重要原因。