Go语言 go程释放操作(退出/销毁)

情况1:

Go语言中,若在子go程中创建一个新 go程,子go程释放(销毁),新创建的go程不会随着子go程的销毁而销毁。

原因:

go程共享堆,不共享栈,go程由程序员在go的代码里显示调度(释放)。

实例:

package main
import (
	"fmt"
	"time"
	"runtime"
)
func test()  {
	for i:=0;i<10;i++{
		fmt.Printf("执行第%d次go程\n",i)
		time.Sleep(time.Second)
	}
	fmt.Println("go程执行完毕!")
}
func main() {
	go func() {
		go test()
		fmt.Println("------aaaaaaaa-------")
		time.Sleep(time.Second)
		fmt.Println("------go程结束--------------")
		/*
		   不管是return  还是  runtime.Goexit(),效果一样
		*/
		//return
		runtime.Goexit()

	}()
	for{
		runtime.GC()
	}
}

从以上实例来看,虽然子go程已经退出,但是在子go程中新建的go程还在执行!原因:go程不共享栈,有自己独立的栈空间。子go程有自己的栈,在子go程中创建的新go程也有自己的栈。

子go程的栈被释放(回收),由于栈独立,因此新创建的go程的栈不会被释放。

情况2:

Go语言中,若在主go程中创建一个新 go程,主go程释放(销毁),新创建的go程随着主go程的销毁而销毁。

原因:

go程共享堆,不共享栈,go程由程序员在go的代码里显示调度(释放)。

实例:

package main

import (
	"fmt"
	"time"
)
func main() {
	go func() {
		for i:=0;i<10;i++{
			fmt.Printf("子go程:执行第%d次操作!\n",i)
			time.Sleep(time.Second)
		}
	}()
	for i:=0;i<3;i++{
		fmt.Println("--------aaaa------")
		time.Sleep(time.Second)
	}
}

从以上实例来看,虽然主go程退出,子go程马上退出。原因:go程共享堆。主go程和新创建的子go程共享一个堆。主go程退出,执行main对应的{ },堆退出。由于是共享堆,所以对应的子go程也会被销毁。

补充:go基础之服务退出问题

最近学习公司微服务的代码,看到每一个微服务的main函数都阻塞在那里,然后里面起的goroutine一直在哪里运行。

package main
import(
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "log"
    "time"
)
func testFunc() error {
    go func(){
        for{
           fmt.Printf("testing....\n")
           time.Sleep(time.Minute)
        }
    }()
    return nil
}
func exitFunc(){
    fmt.Println("i am exiting!")
}
func main(){
    logger := log.New(os.Stdout, "[TestGoroutine]", log.Lshortfile | log.Ldate | log.Ltime) //初始化日志
    exit := make(chan os.Signal,10) //初始化一个channel
    signal.Notify(exit, syscall.SIGINT, syscall.SIGTERM) //notify方法用来监听收到的信号
    testFunc()
    sig := <-exit
    logger.Printf("%s",sig.String())
    exitFunc()
}

代码输出

[root@localhost demoproject]# go run test.go

testing....

^C[TestGoroutine]2018/07/31 19:26:14 test.go:36: interrupt

i am exiting!

可以看到知道按了ctrl+c之后才退出main函数的运行。然后goroutine随之停止运行。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • Golang实现for循环运行超时后自动退出的方法

    前言 for循环是用来遍历数组或数字的.用for循环遍历字符串时,也有 byte 和 rune 两种方式.第一种为byte,第二种rune.下面话不多说了,来一起看看详细的介绍吧. Golang实现for循环 package main import "fmt" func main() { sum := 0 for i := 0; i < 10; i++ { sum += i } fmt.Println(sum) } 跟C语言中一样,可以让前置.后置语句为空. package ma

  • 解决go在函数退出后子协程的退出问题

    该问题来源于自己在读fabric源码时,看到的一个测试代码,在一个函数中启用协程,然后该函数退出了,由于平常没有这样处理过,以及受原有c++函数域的影响,认为函数退出,子协程应该也退出了呀. 这其实是自己对go协程的理解不到位引起的,go的协程作用域不是在某个函数中的,当然,如果那个函数是main函数,就符合要求了. 该代码为solo算法的测试代码: func goWithWait(target func()) *waitableGo { wg := &waitableGo{ done: mak

  • Golang实现超时退出的三种方式

    前段时间发现线上有个服务接口,总是间歇性告警,有时候一天两三次,有时候一天都没有. 告警的逻辑是在一个接口中异步调用了另一个HTTP接口,这个HTTP接口调用出现超时.但是我去问了负责这个HTTP接口的同学,人家说他们的接口相应都是毫秒级别,还截图监控了,有图有真相,我还能说啥. 但是,超时是确实存在的,只是请求还可能没有到人家服务那边. 这种偶发性问题不好复现,偶尔来个告警也挺烦的,第一反应还是先解决问题,思路也简单,失败后重试. 解决方法 且不谈重试策略,先说说什么时候触发重试. 我们可以在

  • Golang信号处理及如何实现进程的优雅退出详解

    Linux系统中的信号类型 各操作系统的信号定义或许有些不同.下面列出了POSIX中定义的信号. 在linux中使用34-64信号用作实时系统中. 命令 man 7 signal 提供了官方的信号介绍.也可以是用kill -l来快速查看 列表中,编号为1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的),编号为32 ~ 63的信号是后来扩充的,称做可靠信号(实时信号).不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号丢失,而后者不会. Linux支持的标准信号有以下一

  • golang 阻止主goroutine退出的操作

    1:for //使用无线循环 for{ } 如果想退出 for { reutrn } 例如:启动三个 goroutine 等待三个 goroutine 执行结束一下 退出主 goroutine var c bool = false var nums int = 0 for i := 0; i < 3; i++ { go func() { fmt.Println("begin------------end") time.Sleep(10 * time.Second) nums++

  • Go语言 go程释放操作(退出/销毁)

    情况1: Go语言中,若在子go程中创建一个新 go程,子go程释放(销毁),新创建的go程不会随着子go程的销毁而销毁. 原因: go程共享堆,不共享栈,go程由程序员在go的代码里显示调度(释放). 实例: package main import ( "fmt" "time" "runtime" ) func test() { for i:=0;i<10;i++{ fmt.Printf("执行第%d次go程\n",i

  • C语言实现支持动态拓展和销毁的线程池

    本文实例介绍了C 语言实现线程池,支持动态拓展和销毁,分享给大家供大家参考,具体内容如下 实现功能 1.初始化指定个数的线程 2.使用链表来管理任务队列 3.支持拓展动态线程 4.如果闲置线程过多,动态销毁部分线程 #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <signal.h> /*线程的任务队列由,函数和参数组成,任务由链表来进行管理*/ typedef str

  • C语言深入讲解内存操作问题

    目录 一.野指针 二.野指针的由来 三.基本原则 四.小结-上 五.常见的内存错误 六.内存操作的规则 七.小结-下 一.野指针 指针变量中的值是非法的内存地址,进而形成野指针 野指针不是 NULL 指针,是指向不可用内存地址的指针 NULL 指针并无危害,很好判断,也很好调试 C 语言中无法判断一个指针所保存的地址是否合法 二.野指针的由来 局部指针变量没有被初始化 指针所指向的变量在指针之前被销毁 使用已经释放过的指针 进行了错误的指针运算 进行了错误的强制类型转换 下面看一个示例: #in

  • C语言进阶二叉树的基础与销毁及层序遍历详解

    单值二叉树 难度简单 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树. 只有给定的树是单值二叉树时,才返回true:否则返回false. 示例 1: 输入:[1,1,1,1,1,null,1]输出:true 示例 2: 输入:[2,2,2,5,2]输出:false 提示: 给定树的节点数范围是[1, 100]. 每个节点的值都是整数,范围为[0, 99]. 解1: 最简单易懂的解法,先序遍历一遍,把每个节点都和那个根节点的val值相比.最后判断flag是否为真,若为假,则表明树中有

  • C语言中的文件操作详解

    目录 1.为什么使用文件 2.什么是文件 2.1程序文件 2.2数据文件 2.3文件名 3.文件的打开和关闭 3.1文件指针 3.2文件的打开和关闭 4.文件的顺序读写 5.文件的随机读写 5.1fseek 5.2ftell 5.3rewind 6.文本文件和二进制文件 7.文件读取结束的判定 7.1被错误使用的feof 8.文件缓冲区 结论 1.为什么使用文件 在学习结构体时,写了一个简易的通讯录的程序,当程序运行起来的时候,可以在通讯录中增加和删除数据,此时数据是存放在内存当中的,当程序退出

  • python 使用事件对象asyncio.Event来同步协程的操作

    事件对象asyncio.Event是基于threading.Event来实现的. 事件可以一个信号触发多个协程同步工作, 例子如下: import asyncio import functools def set_event(event): print('setting event in callback') event.set() async def coro1(event): print('coro1 waiting for event') await event.wait() print(

  • 易语言编程命令调用操作大全

    目录 一. 命令概述 二. 命令的格式 三. 命令的参数 四. 命令的返回值 五. 命令嵌套调用 六. 数组参数与数组返回值 七. 流程控制类命令 八. 算术运算命令 九. 逻辑比较 十. 位运算命令 十一.     数组操作命令 十二.     环境存取命令 十三.     拼音处理命令 十四.     文本操作命令 十五.     时间操作命令 十六.     数值转换命令 十八.     磁盘操作命令 二十.     系统处理命令 二十一.           媒体播放命令 二十二.   

  • GO语言协程创建使用并通过channel解决资源竞争

    目录 创建协程 主协程终止,子协程也终止 runtime包 Gosched让出CPU时间片 Goexit立即结束当前协程 GOMAXPROCS设置并行CPU核数最大值,并返回之前的值 runtime.NumGoroutine()获取当前运行中的goroutine数量 多任务资源竞争问题 通过channel解决资源竞争问题 主协程如何等其余协程完再退出 创建协程 goroutine是go的设计核心,就是协程主协程终止了,子协程也终止 package main import ( "fmt"

  • C语言中文件常见操作的示例详解

    目录 文件打开和关闭 文件写入 文件读取 fseek函数 ftell函数 Demo示例 解决读取乱码 FILE为C语言提供的文件类型,它是一个结构体类型,用于存放文件的相关信息.文件打开成功时,对它作了内存分配和初始化. 每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节. 一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便. 文件打开和关闭 C语言的安全文件打开函数为_wfopen_s和_fopen_s

  • go语言map字典删除操作的方法

    本文实例讲述了go语言map字典删除操作的方法.分享给大家供大家参考.具体分析如下: 这里先构造了一点map,添加了青岛.济南.烟台三地的拼音和汉字字典,然后删除青岛,最后查看青岛是否还存在 复制代码 代码如下: package main import "fmt" func main(){     var pc map[string] string     pc = make(map[string] string)     pc["qingdao"] = "

随机推荐