zoukankan      html  css  js  c++  java
  • 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)
    	}
    }
  • 相关阅读:
    lammps温度云图
    MS中石墨烯建模
    把网页上的内容保存为PDF格式
    lammps 计算热导率
    tomcat错误:严重 [RMI TCP Connection(3)-127.0.0.1] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception
    面向接口编程
    ms中使用AC模块建模时候,保持单个分子的键长 键角不发生变化。
    Python读取文件报错
    debug记录
    网络流
  • 原文地址:https://www.cnblogs.com/alin-qu/p/8545553.html
Copyright © 2011-2022 走看看