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
    */
  • 相关阅读:
    自适应图形的绘制
    红色椭圆、蓝色正方形、黄色三角形、紫色五角星
    [2020牛客寒假算法基础集训营2]G-判正误
    [2020牛客寒假算法基础集训营1]I-nico和niconiconi
    [2020牛客寒假算法基础集训营1]H-nozomi和字符串
    [2020牛客寒假算法基础集训营1]A-honoka和格点三角形
    约瑟夫环以及其变种集合
    unsign long long 与 long long
    【POJ-3279】Fliptile
    B--Bookshelf 2
  • 原文地址:https://www.cnblogs.com/yaowen/p/8082367.html
Copyright © 2011-2022 走看看