Golang面试题五(Goroutine)

目录

1.Goroutine底层原理

定义

2.Goroutine与线程的区别

3.Goroutine泄露的场景

4.Go如何查看正在执行的goroutine数量

runtime.NumGoroutine()

pprof包

5.如何控制goroutine并发数量

使用semaphore

使用channel


1.Goroutine底层原理

定义

Goroutine是Go语言的协程(轻量级线程),是GO支持高并发的基础,属于用户态线程,由Go runtime管理而不是操作系统。

2.Goroutine与线程的区别

3.Goroutine泄露的场景

4.Go如何查看正在执行的goroutine数量

runtime.NumGoroutine()

在Go语言中,要查看当前正在执行的goroutine数量,可以使用runtime包中的NumGoroutine函数。这个函数返回当前程序中活跃的goroutine的数量。

下面是一个简单的示例代码,展示如何使用runtime.NumGoroutine()来打印当前goroutine的数量:

package main

import (
	"fmt"
	"runtime"
)

func main() {
	// 打印当前goroutine的数量
	fmt.Println("Number of active goroutines:", runtime.NumGoroutine())

	// 创建一个新的goroutine
	for i := 0; i < 5; i++ {
		go func() {
			// 在新的goroutine中执行的操作
			fmt.Println("Hello from goroutine")
		}()
	}

	// 再次打印goroutine的数量
	fmt.Println("Number of active goroutines after creating a new one:", runtime.NumGoroutine())
}

pprof

如果你想要更详细的goroutine信息,比如它们的堆栈跟踪,你可以使用pprof包来获取这些信息。这里是如何使用pprof来获取goroutine信息的一个简单例子:

package main

import (
	"net/http"
	"runtime/pprof"
)

func main() {
	http.HandleFunc("/goroutines", func(w http.ResponseWriter, r *http.Request) {
		pprof.Lookup("goroutine").WriteTo(w, 1)
	})

	go http.ListenAndServe(":6060", nil)

	// 主goroutine中可以做一些其他事情,或者等待
	select {}
}

5.如何控制goroutine并发数量

从Go 1.16开始,官方提供了一个更强大的信号量实现。这个包提供了更高级的信号量功能,可以更好地控制并发。

使用semaphore

package main

import (
	"context"
	"fmt"
	"golang.org/x/sync/semaphore"
	"sync"
	"time"
)

func worker(id int, s *semaphore.Weighted, wg *sync.WaitGroup) {
	defer wg.Done()
	// 释放许可证
	defer s.Release(1)
	fmt.Printf("Worker %d started\n", id)
	time.Sleep(time.Second) // 模拟工作
	fmt.Printf("Worker %d finished\n", id)
}

func main() {
	var wg sync.WaitGroup
	s := semaphore.NewWeighted(3) // 最多允许3个goroutine并发执行

	for i := 1; i <= 10; i++ {
		wg.Add(1)
		// 请求一个许可证
		if err := s.Acquire(context.Background(), 1); err != nil {
			fmt.Println("Failed to acquire semaphore:", err)
			return
		}
		go worker(i, s, &wg)
	}

	wg.Wait()
}

使用channel

package main

import (
	"fmt"
	"runtime"
	"sync"
)

func main() {
	fmt.Println("Number of active goroutines:", runtime.NumGoroutine())
	ch := make(chan int, 3)
	for i := 1; i <= 3; i++ {
		ch <- i
	}
	wg := sync.WaitGroup{}
	wg.Add(10)
	for i := 0; i < 10; i++ {
		select {
		case ii := <-ch:
			go func(ii int) {
				defer wg.Done()
				fmt.Printf("gid is %d + bus is %d \n", ii, i)
				ch <- ii
			}(ii)
		}

	}
	fmt.Println("Number of active goroutines:", runtime.NumGoroutine())
	wg.Wait()
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值