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 */