原文链接 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)
}
}

最新文章

  1. eclipse中outline中图标的含义
  2. css3 半个字符美化方法
  3. 【转】VMware 11安装Mac OS X 10.10
  4. HW5.27
  5. How to open .ccproj in VS2010?
  6. jQuery获取鼠标移动方向2
  7. OpenCV——使用ROI进行图像切割
  8. 网络资源(3) - iBatis视频
  9. 本地通过Eclipse链接Hadoop操作Mysql数据库问题小结
  10. java学习(三) java 中 mongodb的各种操作
  11. Asp.Net 常用工具类之Office—Excel导入(5)
  12. 使用 libdvm.so 内部函数dvm* 加载 dex
  13. 在无人值守程序(服务)中调用Microsoft Graph
  14. Apache Spark Jobs 性能调优
  15. WIMLIB-CAPTURE捕获说明
  16. c/c++ 标准库 string
  17. 2018.10.31 NOIP模拟 一些情报(倍增)
  18. 简单prufer应用
  19. 号称简明实用的django上手教程
  20. whlie and for

热门文章

  1. 命令行音乐播放器 CMus
  2. Linux中/etc/passwd 和 /etc/shadows 详解
  3. beanshell解析json(从简单到复杂)
  4. NET Core准备:使用Hyper-V安装Ubuntu Server 16.10
  5. Linux下无法挂载U盘
  6. Ubuntu18.10设置静态IP、DNS、卸载无用软件
  7. linux下火狐浏览器安装flash player插件
  8. 表单和HTML5
  9. 洛谷 P1137 旅行计划
  10. ESP8266串口WiFi扩展板详解