zoukankan      html  css  js  c++  java
  • go14--并发concurrency,Goroutine ,channel

    package main
    
    /**
    
    并发concurrency
    
    很多人都是冲着 Go 大肆宣扬的高并发而忍不住跃跃欲试,但其实从
    源码的解析来看,goroutine 只是由官方实现的超级“线程池”而已。
    不过话说回来,每个实例 4-5KB 的栈内存占用和由于实现机制而大幅
    减少的创建和销毁开销,是制造 Go 号称的高并发的根本原因。另外,
    goroutine 的简单易用,也在语言层面上给予了开发者巨大的便利。
    
    并发不是并行:
    并发切换时间片,单核是没有并行的,只有一个线程,在并行则是直接利用
    多核实现多线程的运行,多核是并行,有多个线程,但 Go 可以设置使用核数,以发挥多核计算机
    的能力。
    
    高并发:因为创建销毁的很快,每一个占内存很小,
    Goroutine 奉行通过通信来共享内存,而不是共享内存来通信。
    
    */
    import (
        "fmt"
        "runtime"
        "time"
    )
    
    func main1() {
        go GO()                     //这就是一个Goroutine,运行了一个Goroutine,
        time.Sleep(2 * time.Second) //暂停2秒钟,不暂停是不会输出的GOGOGO的,
    }
    
    func GO() {
        fmt.Println("GOGOGO")
    }
    
    func main2() {
        c := make(chan bool) //创建一个channel
        go func() {          //go后面接一个匿名函数
            fmt.Println("GGGGGOOOOOO")
            c <- true //channel中存入true或false随便,
        }()
        <-c //从channel中取出来,go启动一个Goroutine之后main函数就执行到<-c并且阻塞了,因为他在等着从
        //channel中取出东西来,只有c <- true执行了,放入东西到channel了,main就可以取出东西来了,
        //通知main函数,他那里执行完毕了,main就继续执行完了
    }
    
    func main3() {
        c := make(chan bool)
        go func() {
            fmt.Println("GGGGGOOOOOO")
            c <- true //执行打印v,执行fmt.Println(v),
            close(c)  //关闭不再迭代,不关闭则一直打印死锁了
        }()
        for v := range c { //迭代channel的时候,一直在等待有值进去,才可以取出来,在打印出来,
            fmt.Println(v)
        }
        /*
            GGGGGOOOOOO
            true
        */
    }
    
    func main() {
        runtime.GOMAXPROCS(runtime.NumCPU()) //返回当前cpu的核数,并利用多核操作Goroutine(Goroutine是线程池)
        c := make(chan bool)
        for i := 0; i < 10; i++ {
            go GO1(c, i) //启动9个goroutine
        }
        <-c //告诉main函数可以退出了
    }
    
    func GO1(c chan bool, index int) {
        a := 1
    
        for i := 0; i < 100000000; i++ {
            a += 1
        }
        fmt.Println(index, a)
        if index == 9 { //启动第九个goroutine的时候就可以告诉main函数可以退出了,
            //多核的时候index=9不一定是最后执行的,所以不一定会执行9遍,有可能执行一遍就退出了,解决方法:缓存的channel
            c <- true
        }
    }
    package main
    
    import (
        "fmt"
        "runtime"
    )
    
    //缓存的channel
    func main() {
        runtime.GOMAXPROCS(runtime.NumCPU())
        c := make(chan bool, 10) //缓存的channel,缓存10个,
        for i := 0; i < 10; i++ {
            go GO1(c, i)
        }
        for i := 0; i < 10; i++ {
            <-c //取10次,就知道goroutine执行完了,这样就保证了能够打印10 次
        }
    }
    
    func GO1(c chan bool, index int) {
        a := 1
    
        for i := 0; i < 100000000; i++ {
            a += 1
        }
        fmt.Println(index, a) //,这样就保证了能够打印10 次
        c <- true             //存10次
    }
    
    /*
        9 100000001
        5 100000001
        0 100000001
        8 100000001
        7 100000001
        4 100000001
        1 100000001
        2 100000001
        6 100000001
        3 100000001
    */
    package main
    
    import (
        "fmt"
        "runtime"
        "sync" //有一个任务组,每完成一个任务就减一,等任务数为0的时候任务就完成了
    )
    
    //第二种解决方案:同步,通过同步包实现多个Goroutine 打印内容
    func main() {
        runtime.GOMAXPROCS(runtime.NumCPU())
        wg := sync.WaitGroup{} //创建一个任务组
        wg.Add(10)             //添加10个任务
    
        for i := 0; i < 10; i++ {
            go GO1(&wg, i) //添加10个Goroutine
        }
    
        wg.Wait() //等待
    }
    
    func GO1(wg *sync.WaitGroup, index int) {
        fmt.Println(index) //打印就是一次任务
        wg.Done()          //任务完成一次
    }
    
    /*
        0 9 1 2 3 4 5 6 7 8
    */
  • 相关阅读:
    HDOJ 2095 find your present (2)
    HDOJ 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
    九度 1337 寻找最长合法括号序列
    九度 1357 疯狂地Jobdu序列
    HDOJ 1280 前m大的数
    九度 1343 城际公路网
    九度 1347 孤岛连通工程
    HDOJ 2151 Worm
    九度 1342 寻找最长合法括号序列II
    九度 1346 会员积分排序
  • 原文地址:https://www.cnblogs.com/yaowen/p/8082367.html
Copyright © 2011-2022 走看看