Goroutines和Channels

原文链接 https://golangbot.com/goroutines/

Goroutines

Goroutines 可以被认为是多个函数或方法同时允许。可以认为是一个轻量级的线程。与线程的花费相比是非常小的。

与线程相比的优势

  • Goroutines 非常的轻量级,只需要几kb的内存分配 并且是可以根据需要动态可伸缩的。而线程的内存分配大小是固定的
  • Goroutines 可以多路复用到几个OS线程中。可能只有一个线程对应到很多歌Goroutines.如果有任何一个Goroutine等待了 比如说需要用户输入 那么另外一个OS线程就会被创建 然后剩下的Goroutines 就会被移动到新的OS线程中被执行
  • Goroutines使用channels沟通。channels被设计在多个Goroutines共享内存时 防止竞态的发生。channels可以被认为是Goroutines的沟通管道

开始运行一个Goroutine

例子

package main

import (
"fmt"
)

func hello() {
fmt.Println("Hello world goroutine")
}
func main() {
go hello()

//time.Sleep(1 * time.Second)
//fmt.Println("main function")

fmt.Println("main function")
}
执行这段程序之后 不会有任何输出

  • 当执行一个Goroutine,goroutine会立即返回并执行下一段代码 以至于任何goroutine的返回值都会被忽略掉
  • 当主Goroutine停止之后 其它任何的Goroutie也都会被终止

channels

  • channels可以认为是Goroutines的沟通通道。

例子

package main
import (
"fmt"
)

func hello(done chan bool){
fmt.Println("hello goroutine")
done <- true
}

func main(){
done := make(chan bool)

go hello(done)

<-done

fmt.Println("main function")
}

  • <-done 这行代码会阻止程序继续往下运行 直到Goroutine写了数据到这个channel之中 然后channel里面收到数据之后 程序会继续往下进行
  • 如果需要等待多个Goroutine 则需要发送多个值到channel 也相应的要有多个相对应的接收channel

Deadlock

  • 如果从一个Goroutine通过通道发送了数据 那么被认为会有另外一个Goroutine接收相对应的数据 如果没有的话就会产生paninc 也就发生了死锁

  • 相似的 如果Goroutine从一个channel钟等待数据 那么应该会有另外一个Goroutine通过channle发送数据 否则的话也会发生paninc

例子

package main

func main() {
ch := make(chan int)
ch <- 5
}

  • fatal error: all goroutines are asleep - deadlock!

Unidirectional channels(单向channel)

例子1

package main

import "fmt"

func sendData(sendch chan<- int) {
sendch <- 10
}

func main() {
sendch := make(chan<- int) //只运行向channel发送数据

go sendData(sendch)
fmt.Println(<-sendch) //这里从channel钟接收数据 则报错
}

例子2

//这里定义了一个只往channel发送的类型
func sendData(sendch chan<- int) {
sendch <- 10
}

func main() {
chnl := make(chan int)
go sendData(chnl)
fmt.Println(<-chnl)
}

Closing channels and for range loops on channels

  • 发送者是可以关闭channel 来通知接收者没有数据要往这个channel中发送了
  • 接收者可以使用另外一个变量来检测是否channel已经关闭了 v, ok := <- ch

例子

package main

import (
"fmt"
)

func producer(c chan int){
for i:=0; i < 10; i++{
c <- i
}

close(c)
}

func main() {
ch := make(chan int)

//for{
// v,ok := <-ch
// if ok == false{
// break
// }
//
// fmt.Println("Received ",v,ok)
//}

for v := range ch{
fmt.Println("Received ",v)
}
}

posted @ 2018-03-11 20:07  alin_qu  阅读(219)  评论(0)    收藏  举报