分享
  1. 首页
  2. 文章

Go 语言基础——协程(goroutine)&共享内存线程安全

迪丽热BUG · · 2144 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

协程(goroutine)是更轻量级的线程

比Java中的线程效率更高

协程语法
go func() {
 //...
}()

一旦主goroutine中的代码执行完毕,当前的Go程序就会结束运行,无论其他的 goroutine是否已经在运行了。

让主goroutine等待其它 goroutine:
for i := 0; i < 10; i++ {
 go func() {
 fmt.Println(i)
 }()
}
time.Sleep(time.Millisecond * 1000)
//goroutine 完成的时间很可能小于设置的等待时间,那么这就会造成多余的等待时间
怎么才能让goroutine执行完后立刻执行下一个goroutine呢?

go语言提供的WaitGroup可以实现这样的功能.

代码改造:

var wg sync.WaitGroup
for i := 0; i < 10; i++ {
 wg.Add(1)//每启动一个协程增加一个等待
 go func() {
 fmt.Println(i)
 wg.Done()//告诉协成等待的事务已经完成
 }()
}
/*
这样我们就不用设置等待时间了,但是执行输出的内容是这样的: 3 7 4 8 8 8 9 10 10 10, 很显然这种方式不能保证goroutine拿到唯一整数
*/
如何保证每个线程拿到的数是惟一的?

代码改造:

var wg sync.WaitGroup
for i := 0; i < 10; i++ {
 wg.Add(1)//每启动一个协程增加一个等待
 go func(j int) {//把j只是个形参可以任意命名
 fmt.Println(j)
 wg.Done()//告诉协成等待的事务已经完成
 }(i)//把实参i传递给形参j
}
//执行结果:0 2 1 6 3 4 5 8 7 9

我们把i值传递给j,i的变化不会影响j的值,所以输出的结果是唯一的

共享内存线程安全
func TestCounter(t *testing.T) {
 counter := 0
 for i := 0; i < 5000; i++ {
 go func() {
 counter++
 }()
 }
 time.Sleep(1 * time.Second)
 t.Logf("counter = %d", counter)
}
//执行结果: 4760 出现了线程安全的问题

和大多数语言一样go也支持加锁保证线程的安全:

func TestCounterWaitGroup(t *testing.T) {
 var mut sync.Mutex//创建锁对象
 var wg sync.WaitGroup
 counter := 0
 for i := 0; i < 5000; i++ {
 wg.Add(1)//每启动一个协程增加一个等待
 go func() {
 defer func() {
 mut.Unlock()//释放锁
 }()
 mut.Lock()//开启锁
 counter++
 wg.Done()//告诉协成等待的事务已经完成
 }()
 }
 wg.Wait()//等待协程
 t.Logf("counter = %d", counter)
}

码字不易如果对你有帮助请给个关注

爱技术爱生活 QQ群: 894109590


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:迪丽热BUG

查看原文:Go 语言基础——协程(goroutine)&共享内存线程安全

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
2144 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏