Golang并发

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

在编写 Socket 网络程序时,需要提前准备一个线程池为每一个 Socket 的收发包分配一个线程。开发人员需要在线程数量和 CPU 数量间建立一个对应关系,以保证每个任务能及时地被分配到 CPU 上进行处理,同时避免多个任务频繁地在线程间切换执行而损失效率。
虽然,线程池为逻辑编写者提供了线程分配的抽象机制。但是,如果面对随时随地可能发生的并发和线程处理需求,线程池就不是非常直观和方便了。能否有一种机制:使用者分配足够多的任务,系统能自动帮助使用者把任务分配到 CPU 上,让这些任务尽量并发运作。这种机制在 Go语言中被称为 goroutine
goroutine 是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理。Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU。

package main

import (
    "fmt"
    "time"
)

//默认启动main函数都会创建一个对应的goroutine
func main() {
    //使用 goroutine创建匿名函数
    go func() {
        var times int
        for {
            times++
            fmt.Println("tick", times)
            time.Sleep(time.Second)
        }
    }()
    // 接受命令行输入, 不做任何事情
    //如果不采用 这种方式也可以采用其他方式
    //因为 golang会默认为main创建一个goroutine  当遇到 go func的时候会重新开启一个goroutine  main函数的goroutine
    //继续执行下去
    var input string
    fmt.Scanln(&input)
}

Go语言中如果两个或者多个 goroutine 在没有互相同步的情况下,访问某个共享的资源,并试图同时读和写这个资源,就处于相互竞争的状态,这种情况被称作竞争状态(race candition)。
竞争状态的存在是让并发程序变得复杂的地方,十分容易引起潜在问题。对一个共享资源的读和写操作必须是原子化的,换句话说,同一时刻只能有一个 goroutine 对共享资源进行读和写操作。

package main

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

var (
    // counter 是所有goroutine 都要增加其值的变量
    counter int
    // wg 用来等待程序结束
    wg sync.WaitGroup
)
// main 是所有Go 程序的入口
func main() {
    // 计数加 2,表示要等待两个goroutine
    wg.Add(2)
    // 创建两个goroutine
    go incCounter()
    go incCounter()
    // 等待 goroutine 结束
    wg.Wait()
    fmt.Println("Final Counter:", counter)
}
// incCounter 增加包里counter 变量的值
func incCounter() {
    // 在函数退出时调用Done 来通知main 函数工作已经完成
    defer wg.Done()
    for count := 0; count < 2; count++ {
        // 捕获 counter 的值
        value := counter
        // 当前 goroutine 从线程退出,并放回到队列
        runtime.Gosched()
        // 增加本地value 变量的值
        value++
        // 将该值保存回counter
        counter = value
    }
}
最后输出结果值为2 多次运行的结果也可能会出现 3 4
原因是每个goroutine 线程都会覆盖前一个goroutine所做的操作,也就是说counter每次只能由一个线程操作
传统开发者模式需要维护线程池与CPU的关系 ,Golang当中也提供支持。
采用 如下设置多核运行  runtime.NumCPU获取 当前的CPU数量
runtime.GOMAXPROCS(runtime.NumCPU())

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

本文来自:简书

感谢作者:

查看原文:Golang并发

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

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