垃圾回收(gc)

主要看了一下py与go的方式,萌新的理解。

一般的时候,好像一般还是更多的关心内存的申请这一块。

学习from:https://blog.csdn.net/u010649766/article/details/80582153

垃圾回收是个啥?

申请的一些内存,本身这些内存已经没有用了,或者已经没有办法访问到这块内存,或者这些内存应该被释放掉又没被释放。

那么需要对这些垃圾内存进行回收。

内存泄露是个啥?

产生的原因:程序在运行的时候,会不断地动态开辟的存储空间,这些存储空间在在运行结束之后后并没有被及时释放掉。应用程序在分配了某段内存之后,没有一个很好的设计回收机制,导致系统没有回收这部分内存。 

实习的时候(python),mentor有在找过一个内存泄露的原因,菜鸡一枚,也没能帮上什么忙,现在了解一下。

也就是我们在new一些对象,或者申请的一些内存,由于自己的疏忽,没有及时在合适的地方进行释放,并且垃圾回收没有找到这块内存进行释放,导致出现out of memory(oom错误)。

引用计数(reference counting)

这是最简单,最常见?的一种垃圾回收算法。做法:对每个对象维护一个引用计数,当引用该对象的对象被销毁或更新时被引用对象的引用计数自动减一,当被引用对象被创建或被赋值给其他对象时引用计数自动加一。当引用计数为0时则立即回收对象。

这种方法的优点是实现简单,并且内存的回收很及时。这种算法在内存比较紧张和实时性比较高的系统中使用的比较广泛,如,php,python等。简单引用计数算法也有明显的缺点:

  • 频繁更新引用计数降低了性能。一种简单的解决方法就是编译器将相邻的引用计数更新操作合并到一次更新;还有一种方法是针对频繁发生的临时变量引用不进行计数,而是在引用达到0时通过扫描堆栈确认是否还有临时对象引用而决定是否释放。等等还有很多其他方法。
  • 循环引用问题。当对象间发生循环引用时引用链中的对象都无法得到释放,那么要做的是避免循环引用,怎么避免还需额外了解。

标记-清除(mark and sweep)

该方法分为两步,标记从根变量开始迭代得遍历所有被引用的对象,对能够通过应用遍历访问到的对象都进行标记为“被引用”;标记完成后进行清除操作,对没有标记过的内存进行回收(回收同时可能伴有碎片整理操作)。这种方法解决了引用计数的不足,但是也有比较明显的问题:每次启动垃圾回收都会暂停当前所有的正常代码执行,回收是系统响应能力大大降低!当然后续也出现了很多mark&sweep算法的变种(如三色标记法)优化了这个问题。

标记和扫描算法
任何垃圾收集算法都必须执行2个基本操作。一,它应该能够检测所有无法访问的对象;其次,它必须回收垃圾对象使用的堆空间,并使空间再次可用于程序。
上述操作由标记和扫描算法分两个阶段执行:
1)标记阶段
2)扫描阶段

golang使用的是标记-清除,

问题?:对于对用户响应事件有要求的后端程序,golang gc时的stop the world是一个很难办的事情(意思是在http请求服务器在gc的时候不动了)。

stop the world(等待所有的M休眠;此时所有的业务逻辑代码都停止)

三色标记:

垃圾回收(gc)_第1张图片

你可能感兴趣的:(好东西)