iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >Go语言中怎么对栈进行处理
  • 760
分享到

Go语言中怎么对栈进行处理

2024-04-02 19:04:59 760人浏览 泡泡鱼
摘要

本篇文章为大家展示了Go语言中怎么对栈进行处理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、线程栈(thread stacks)介绍在我们研究Go的栈处理方式之

本篇文章为大家展示了Go语言中怎么对栈进行处理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

一、线程栈(thread stacks)介绍

在我们研究Go的栈处理方式之前,我们先来看看传统语言,比如C是如何进行栈管理的。

当你启动一个C实现的thread时,C标准库会负责分配一块内存作为这个线程的栈。标准库分配这块内存,告诉内核它的位置并让内核处理这个线程 的执行。不过当这块内存不够用时,问题就来了,我们来看一下下面这个函数:

int a(int m, int n) {     if (m == 0) {         return n + 1;     } else if (m > 0 && n == 0) {         return a(m – 1, 1);     } else {         return a(m – 1, a(m, n – 1));     } }

这个函数大量使用递归,执行a(4, 5)就会降所有栈内存耗尽。要解决这个问题,你可以调整标准库给线程栈分配的内存块的大小。但是全线提高栈大小意味着每个线程都会提高栈的内存使用量,即 便它们不是大量采用递归方式的。这样一来,你将用光所有内存,即便你的程序还尚未使用栈上的内存。

另外一种可选的解决方法则是为每个线程单独确定栈大小。这样一来你就不得不完成这样的任务:根据每个线程的需要,估算它们的栈内存的大小。这将是 创建线程的难度超出我们的期望。想搞清楚一般情况下一个线程栈需要多少内存是不可行的,即便是通常情况也是非常困难的。

二、Go是如何应对这个问题的

Go运行时会试图按需为goroutine提供它们所需要的栈空间,而不是为每个goroutine分配一个固定大小的栈空间。这样可以把程序员 们从决定栈空间大小的烦心事中解脱了出来。不过Go核心团队正在尝试切换到另外一种方案,这里我将尝试阐述旧方案以及它的缺点,新方案以及为何要 做出如此改变。

三、分段栈(Segmented Stacks)

分段栈(segmented stacks)是Go语言最初用来处理栈的方案。当创建一个goroutine时,Go运行时会分配一段8K字节的内存用于栈供goroutine运行使 用,我们让goroutine在这个栈上完成其任务处理。

当我们用光这8K字节的栈空间后,问题随之而来。为了解决这个问题,每个go函数在函数入口处都会有一小段代码(called prologue),这段代码会检查是否用光了已分配的栈空间,如果用光了,这段代码会调用morestack函数。

morestack函数会分配一段新内存用作栈空间,接下来它会将有关栈的各种数据信息写入栈底的一个struct中(译注:下图中Stack info),包括上一段栈的地址。有点我们拥有了一个新的栈段(stack segment),我们将重启goroutine,从导致栈空间用光的那个函数(译注:下图中的Foobar)开始执行。这就是所谓的“栈分裂 (stack split)”。

下面的栈示意图刚好是我们进行栈分裂后的情形:

Go语言中怎么对栈进行处理

在新栈的底部,我们插入了一个栈入口函数lessstack。我们不会调用该函数,设置这个函数就是用于我们从那个导致我们用光栈空间的函数(译 注:Foobar)返回时用的。当那个函数(译注:Foobar)返回时,我们回到lessstack(这个栈帧),lessstack会查找 stack底部的那个struct,并调整栈指针(stack pointer),使得我们返回到前一段栈空间。这样做之后,我们就可以将这个新栈段(stack segment)释放掉,并继续执行我们的程序了。

四、分段栈(Segmented stacks)的问题

分段栈给了我们具备按需伸缩能力的栈。程序员们无需担心计算栈的大小了,启动一个新的goroutine代价低廉并且程序员不会知道栈将增长多 大。

这就是直到目前Go语言处理stack增长的方法,但是这个方法有个瑕疵。那就是栈缩小会是一个相对代价高昂的操作。如果你在一个循环遇到栈分裂 (stack split),你会最有感触。一个函数会增加栈空间,做栈分裂,返回并释放栈段(stack segment)。如果你在一个循环中进行这些,你会付出很大的代价(性能方面)。

这就是所谓的“hot split”问题。它也是Go核心开发组更换到一个新的栈管理方案-栈拷贝(stack copying)的主要原因。

五、栈拷贝(stack copying)

栈拷贝初始阶段与分段栈类似。goroutine在栈上运行着,当用光栈空间,它遇到与旧方案中相同的栈溢出检查。但是与旧方案采用的保留一个返 回前一段栈的link不同,新方案创建一个两倍于原stack大小的新stack,并将旧栈拷贝到其中。这意味着当栈实际使用的空间缩小为原先的 大小时,go运行时不用做任何事情。栈缩小是一个无任何代价的操作。此外,当栈再次增长时,运行时也无需做任何事情,我们只需要重用之前分配的空 闲空间即可。

六、栈是怎么拷贝的

拷贝栈听起来简单,但实际上它是一件有难度的事情。因为Go中栈上的变量都有自己的地址,一旦你拥有指向栈上变量的指针,这种情况下你就无法如你 所愿。当你移动栈时,指向原栈的指针都将变为无效指针。

幸运的是,只有在栈上分配的指针才能指向栈上的地址。这点对于内存安全是极其必要的,否则,程序可能会访问到已不再使用了的栈上的地址。

由于我们需要知道那些需要被垃圾收集器回收的指针的位置,因此我们知道栈上哪些部分是指针。当我们移动栈时,我们可以更新栈里地指针使其指向新的 目标地址,并且所有相关的指针都要被照顾到。

由于我们使用垃圾回收的信息来协助完成栈拷贝,因此所有出现在栈上的函数都必须具备这些信息。但事情不总是这样的。因为Go运行时的大部分代码是 用C编写的,大量的运行时调用没有指针信息可用,这样就无法进行拷贝。一旦这种情况发生,我们又不得不退回到分段栈方案,并接受为其付出的高昂代 价。

这就是当前Go运行时开发者大规模重写Go runtime的原因。那些无法用Go重写的代码,比如调度器和垃圾收集器的内核,将在一个特殊的栈上执行,这个特殊栈的size由runtime开发者 单独计算确定。

除了让栈拷贝成为可能之外,这个方法还会使得我们在未来能够实现出并发垃圾回收等特性。

七、关于虚拟内存

另外一种不同的栈处理方式就是在虚拟内存中分配大内存段。由于物理内存只是在真正使用时才会被分配,因此看起来好似你可以分配一个大内存段并让操 作系统处理它。下面是这种方法的一些问题

首先,32位系统只能支持4G字节虚拟内存,并且应用只能用到其中的3G空间。由于同时运行百万goroutines的情况并不少见,因此你很可 能用光虚拟内存,即便我们假设每个goroutine的stack只有8K。

第二,然而我们可以在64位系统中分配大内存,它依赖于过量内存使用。所谓过量使用是指当你分配的内存大小超出物理内存大小时,依赖操作系统保证 在需要时能够分配出物理内存。然而,允许过量使用可能会导致一些风险。由于一些进程分配了超出机器物理内存大小的内存,如果这些进程使用更多内存 时,操作系统将不得不为它们补充分配内存。这会导致操作系统将一些内存段放入磁盘缓存,这常常会增加不可预测的处理延迟。正是考虑到这个原因,一 些新系统关闭了对过量使用的支持。

上述内容就是Go语言中怎么对栈进行处理,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网VUE频道。

--结束END--

本文标题: Go语言中怎么对栈进行处理

本文链接: https://www.lsjlt.com/news/71189.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Go语言中怎么对栈进行处理
    本篇文章为大家展示了Go语言中怎么对栈进行处理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、线程栈(thread stacks)介绍在我们研究Go的栈处理方式之...
    99+
    2024-04-02
  • Go语言中怎么对栈中函数进行内联
    这篇文章主要介绍“Go语言中怎么对栈中函数进行内联”,在日常操作中,相信很多人在Go语言中怎么对栈中函数进行内联问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Go语言中怎么对栈中函数进行内联”的疑惑有所帮助!...
    99+
    2023-06-16
  • Go语言中怎么对Concurrency进行管理
    这篇文章给大家介绍 Go语言中怎么对Concurrency进行管理 ,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。WaitGroup先来了解有什么情境需要使用到  WaitG...
    99+
    2024-04-02
  • 如何在 GO 中使用对象进行自然语言处理?
    自然语言处理(NLP)在计算机科学领域中是一个重要的子领域,它涉及到计算机如何理解和处理人类语言。GO是一种强大的编程语言,因此它可以用于开发自然语言处理应用程序。在本文中,我们将介绍如何使用GO中的对象进行自然语言处理。 首先,让我们了解...
    99+
    2023-09-05
    自然语言处理 shell 对象
  • 如何在 SHELL 中使用 GO 对象进行自然语言处理?
    自然语言处理是人工智能领域中的一个重要分支,它涵盖了文本分析、文本挖掘、机器翻译等多个方面。在 SHELL 中使用 GO 对象进行自然语言处理可以提高代码的可读性和可维护性,同时也可以更加方便地利用 GO 语言的强大特性进行自然语言处理。...
    99+
    2023-09-05
    自然语言处理 shell 对象
  • r语言中怎么进行数据处理
    在R语言中进行数据处理时,常见的操作包括数据清洗、数据转换、数据筛选、数据聚合、数据可视化等。以下是一些常用的数据处理操作: 数据...
    99+
    2024-03-02
    r语言
  • 如何使用Go语言对重定向问题进行处理?
    在网络通信中,重定向是常见的一种情况。当你访问某个网站时,可能会被重定向到另一个网站或页面。在这种情况下,你需要在代码中处理重定向问题,以确保你的程序可以正确地访问目标网站或页面。本文将介绍如何使用Go语言处理重定向问题,并提供演示代码。...
    99+
    2023-09-23
    重定向 leetcode 索引
  • 使用Go语言的切片对数据进行高效处理
    Golang小白一枚,正在不断学习积累知识,现将学习到的知识记录一下,也是将我的所得分享给大家!而今天这篇文章《使用Go语言的切片对数据进行高效处理》带大家来了解一下##content_title#...
    99+
    2024-04-04
  • 怎么在R语言中使用dplyr包对数据进行处理
    这期内容当中小编将会给大家带来有关怎么在R语言中使用dplyr包对数据进行处理,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。数据筛选函数:#可使用filter()函数筛选/查找特定条件的行或者样本#fil...
    99+
    2023-06-08
  • 如何在Go语言中使用容器进行自然语言处理?
    自然语言处理是人工智能领域中最重要的应用之一。在Go语言中,使用容器进行自然语言处理是一种非常高效的方式。本文将介绍如何在Go语言中使用容器进行自然语言处理。 一、什么是容器? 容器是一种轻量级的虚拟化技术,可以在单个操作系统上运行多个独立...
    99+
    2023-10-06
    自然语言处理 容器 实时
  • 如何使用 GO 对象进行高效的自然语言处理?
    自然语言处理(Natural Language Processing,NLP)是人工智能领域中的一个重要领域,它涉及到对人类语言的理解和生成。在实际应用中,自然语言处理技术已经广泛应用于搜索引擎、文本分类、机器翻译、问答系统等领域。在本文中...
    99+
    2023-09-05
    自然语言处理 shell 对象
  • 如何在UNIX系统中利用GO语言进行自然语言处理?
    在当今信息化时代,自然语言处理(NLP)越来越受到人们的关注。作为一种高效的编程语言,GO语言在NLP领域也有着广泛的应用。本文将为大家介绍如何在UNIX系统中利用GO语言进行自然语言处理。 一、GO语言介绍 GO语言是由Google公司开...
    99+
    2023-08-14
    unix 索引 自然语言处理
  • 使用Go语言进行高级异常处理
    在 go 中,处理高级异常的最佳实践包括:使用 try-catch-finally 语句处理异常。创建自定义错误类型以提供更有意义的异常信息。传递错误值以跟踪异常来源。使用恐慌和恢复来处...
    99+
    2024-04-15
    go 异常处理 go语言
  • GO语言在Linux上使用NPM进行自然语言处理,可行吗?
    随着人工智能技术的不断发展,自然语言处理已经成为了最热门的领域之一。自然语言处理技术可以让计算机更好地理解人类语言,进而实现更加智能化的应用。而在自然语言处理领域,NPM是一款非常常用的工具包,它可以帮助我们更加便捷地进行自然语言处理。那...
    99+
    2023-11-10
    linux 自然语言处理 npm
  • 如何在Go语言中使用Numpy进行数据处理?
    Go语言是一种高效、并发性强的编程语言,而Numpy是Python中非常受欢迎的数据处理库。但是,如果您想在Go语言中进行数据处理,该怎么办呢?本文将介绍如何使用Go语言中的Numpy库进行数据处理。 一、Go语言中使用Numpy 使用Go...
    99+
    2023-06-26
    响应 大数据 numpy
  • Android中怎么对cookie进行处理
    本篇文章给大家分享的是有关Android中怎么对cookie进行处理,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。android 客户端 Cookie处理Cookie,有时也用...
    99+
    2023-05-30
    android cookie
  • Node.js中怎么对CORS进行处理
    今天就跟大家聊聊有关Node.js中怎么对CORS进行处理,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。什么是CORSCORS 是“跨域资源共享”的...
    99+
    2024-04-02
  • go语言怎么进行web开发
    Go语言的Web开发流程为:1、选择Web框架;2、设计路由,指定URL如何映射到处理程序;3、处理请求和响应,包括解析请求参数、处理表单数据、设置Cookie等;4、数据库操作,将数据存储在数据库中;5、模板渲染,将数据呈现给用户使用模板...
    99+
    2023-12-13
    go语言web开发 go语言 Golang
  • Python 对象在 Linux 中如何进行自然语言处理?
    自然语言处理(NLP)是人工智能领域的一个重要分支,它主要涉及计算机如何与人类语言进行交互和处理。Python 是一种功能强大的编程语言,它在自然语言处理领域非常受欢迎。本文将介绍如何在 Linux 中使用 Python 对象进行自然语言...
    99+
    2023-11-03
    对象 linux 自然语言处理
  • 如何使用Go语言进行大数据处理?
    使用Go语言进行大数据处理的方法有安装Go语言环境、编写数据处理程序、读取和处理数据、并发处理、写入输出结果等。详细介绍:1、安装Go语言环境:首先,需要在你的计算机上安装Go语言环境。可以从Go官方网站下载并安装适合你操作系统的版本;2、...
    99+
    2023-12-21
    go语言 大数据处理
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作