go获取协程(goroutine)号的实例

论坛 期权论坛 脚本     
niminba   2021-5-23 03:01   1331   0

我就废话不多说了,大家还是直接看代码吧~

func GetGID() uint64 {
    b := make([]byte, 64)
    b = b[:runtime.Stack(b, false)]
    b = bytes.TrimPrefix(b, []byte("goroutine "))
    b = b[:bytes.IndexByte(b, ' ')]
    n, _ := strconv.ParseUint(string(b), 10, 64)
    return n
}

补充:Go语言并发协程Goroutine和通道channel

Go语言并发协程Goroutine

1.1 Go语言竞争状态

有并发,就有资源竞争,如果两个或者多个 goroutine 在没有相互同步的情况下,访问某个共享的资源,比如同时对该资源进行读写时,就会处于相互竞争的状态,这就是并发中的资源竞争。

并发本身并不复杂,但是因为有了资源竞争的问题,就使得我们开发出好的并发程序变得复杂起来,因为会引起很多莫名其妙的问题。

以下代码就会出现竞争状态:

import (
  "fmt"
  "runtime"
  "sync"
)
var (
  count int32
  wg  sync.WaitGroup
)
func main() {
  wg.Add(2)
  go incCount()
  go incCount()
  wg.Wait()
  fmt.Println(count)
}
func incCount() {
  defer wg.Done()
  for i := 0; i < 2; i++ {
    value := count
    runtime.Gosched()
    value++
    count = value
  }
}

count 变量没有任何同步保护,所以两个 goroutine 都会对其进行读写,会导致对已经计算好的结果被覆盖,以至于产生错误结果。

代码中的 runtime.Gosched() 是让当前 goroutine 暂停的意思,退回执行队列runq,让其他等待的 goroutine 运行,目的是为了使资源竞争的结果更明显,下次运行暂停的goroutine时从断点处开始。

分析程序运行过程:

g1 读取到 count 的值为 0;

然后 g1 暂停了,切换到 g2 运行,g2 读取到 count 的值也为 0;

g2 暂停,切换到 g1暂停的位置继续运行,g1 对 count+1,count 的值变为 1;

g1 暂停,切换到 g2,g2 刚刚已经获取到值 0,对其 +1,最后赋值给 count,其结果还是 1;

可以看出 g1 对 count+1 的结果被 g2 给覆盖了,两个 goroutine 都 +1 而结果还是 1。

通过上面的分析可以看出,之所以出现上面的问题,是因为两个 goroutine 相互覆盖结果。

所以我们对于同一个资源的读写必须是原子化的,也就是说,同一时间只能允许有一个 goroutine 对共享资源进行读写操作。 此例子的共享资源就是count

通过go build -race生成一个可以执行文件,然后再运行这个可执行文件,就可以检测资源竞争信息,看到打印出的检测信息。如下

==================
WARNING: DATA RACE
Read at 0x000000619cbc by goroutine 8:
 main.incCount()
   D:/code/src/main.go:25 +0x80// goroutine 8 在代码 25 行读取共享资源value := count
Previous write at 0x000000619cbc by goroutine 7:
 main.incCount()
   D:/code/src/main.go:28 +0x9f// goroutine 7 在代码 28行修改共享资源count=value
Goroutine 8 (running) created at:
 main.main()
   D:/code/src/main.go:17 +0x7e
Goroutine 7 (finished) created at:
 main.main()
   D:/code/src/main.go:16 +0x66//两个 goroutine 都是从 main 函数的 16、17 行通过 go 关键字启动的。
==================
4
Found 1 data race(s)

1.2 锁住共享资源

Go语言提供了传统的同步 goroutine 的机制,就是对共享资源加锁。atomic 和 sync 包里的一些函数就可以对共享的资源进行加锁操作。

1.2.1 原子函数

原子函数能够以很底层的加锁机制来同步访问整型变量和指针

import (
  "fmt"
  "runtime"
  "sync"
  "sync/atomic"
)
var (
  counter int64
  wg   sync.WaitGroup
)
func main() {
  wg.Add(2)
  go incCounter(1)
  go incCounter(2)
  wg.Wait() //等待goroutine结束
  fmt.Println(counter)
}
func incCounter(id int) {
  defer wg.Done()
  for count := 0; count < 2; count++ {
    atomic.AddInt64(&counter, 1) //安全的对counter加1
    runtime.Gosched()
  }
}

上述代码中使用了 atmoic 包的 AddInt64 函数,这个函数会同步整型值的加法,方法是强制同一时刻只能有一个 gorountie 运行并完成这个加法操作。

另外两个有用的原子函数是 LoadInt64 和 StoreInt64。这两个函数提供了一种安全地读和写一个整型值的方式。下面的代码就使用了 LoadInt64 和 StoreInt64 函数来创建一个同步标志,这个标志可以向程序里多个 goroutine 通知某个特殊状态。

import (
  "fmt"
  "sync"
  "sync/atomic"
  "time"
)
var (
  shutdown int64
  wg    sync.WaitGroup
)
func main() {
  wg.Add(2)
  go doWork("A")
  go doWork("B")
  time.Sleep(1 * time.Second)
  fmt.Println("Shutdown Now")
  atomic.StoreInt64(&shutdown, 1)
  wg.Wait()
}
func doWork(name string) {
  defer(]\BCB9/a #9nml!a CB][^Y\	\]	YK[
CB[
B9l!db.eiz/+[9c yb,9c 9.*cc'f.\9$#9i9 9.*cch*9oyy-\9ay`/;`9.i9k9d$yc 9.*cc CB\	[BCBOOB]BK9"ya`&`dB"ya`&`d 9g*:(-bcz f9`9. 9.*% !yi&.*`/9`&`dn:`&`d#yo.b-)y`[H9.bn9$9c yd9y-c yd9yc:f.hy..c"yg*:`&`dy"z)yy-`/9#9y-b9/g9cy/&f. c"yg*:`&`d"yc*9ac.ky( y`/9#9c yb9/g9cy/&f. B"ya`&`d$:`&`d9. 9.*o9i)#yd#;$:`&`dc9c yd9y-[H9/&g*9d#9. 9c9l9k.9h"ya`&`d"z/ B...b:)y`&`d-ac.i)'B`&`d[[;+)9.*[H:e&/9iyx/o[H9. yo-"y. 9yk. 9y:-.yl9kodk. 9yl9k/'):-.yyl9ki!9`'#9i:`&`dd9b-eo#:`ykf9l!.#yz!: ,9n9m*yi;fd9b-`&`do"yb*y.gk9/'#9/l9kan:-.yyi!9a`&`d# {cz h,9i!9l9kBKH[[:-y.b-BX9.b-.#y+.-y#:++ycm: 9y/;f.X9+yam.+y"y. 9.*9m9$;n&o9."c; #9.#y/&  m.9xBg+:+.B*:+n 9.*Sg;B]\HHBH\H\Z[BX	[NB9i[y$9b,9l9kb&z/c:+\i!9+[	NB9i9$9b[ayaiyl9kb&z/c:+\i!9+Y][B9i9."gh`y"y$9b&z/iYY][9i!9`yBOOB]B/#9#`9..*[{+.Xa[YKY\g*:/9#+:`&`d/9cy-&yd#c\[:-y#9cl&`&`d&f.byoLB]\HHBH\H\Z[B[XZ[
HHXZ[[
CB]Z]HXZ[
CB9o 9. 9.*cc[HXH	B][[HHCB	[YKY\[YK
NB][-yCB]Z]	YCBCBCBJ
Hb*
CBHHH	NJ	CB[YKY\
[YK
K.."iy/$y {oy."ghccc9nm/izf.byoy {l,z/-c;nm`&/[`&/CB	]Z]B][ngCBCBK[]KCB[HHB[HHCB[HHB[HH[HH
B-yngOB]."...*.j;n#9&) 9.*c g&i&i&+/c.i"ze&z+%*  9aj9g,9{&'z-d9fx
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP