go 语言 并发,并行,信道

go语言

  并发

  并行

  信道

package main

import (
    "fmt"
    "time"
)
补充:
//并发:看上去在同一时间同时执行,实际是切换执行利用时间片轮转法,同一个CPU进行切换执行
// 并行:是在真正的同一时间两个程序同时进行吗,这个是在多核cpu情况下,同一时刻,两个事情同时进行
//进程:进程是程序执行的最小单位,例如qq进程,迅雷进程,
//   线程: 例如迅雷进程中,有上传,下载,上传就是一个线程,下载就是另一个线程
//   协程:当线程碰到io操作时,就会一直停在那里,这个线程就一直处于浪费状态,此时我可以让这个线程转而去做其他的事,
//       此时,就不是操作系统控制,而是由程序去控制,所以有genevt这个第三方模块,自动实现io切换,这就是单线程下实现并发即协程
// node.js 本身只能在游览器中去执行,于是写了一个引擎,让代码跑在这个引擎上(类似于解释器)就可以跑在服务端上
// 虽然js是一个解释型语言,但是node.js 使用了一个事件驱动,非阻塞i/o模型,运行特别快,碰到io就切
// python 的async/await 协程  http请求用asyncio  异步框架sanic
// python 中要想速度高,就得使用异步编程,异步框架


//go中用关键字go即可,go语言并发性能高,go协程
// go协程原理:go语言一旦跑起来,会在内部建一个很大的线程池,在线程池中go自己写好了算法,自己去调度,遇到io自己去切,自己去执行任务

func test()  {
    fmt.Println("hello go")
}
//协程之间如何进行数据通信,就用信道
func main()  {
    //本质是goroutine  当新开的线程没结束,主线程已经结束了,所以要想打印,就得等待一会
    go test()
    go test()
    go test()
    go test()
    go test()    //是开了好多,速度很快
    time.Sleep(time.Second*2)//Second表示秒 ,此时表示睡2秒
}

信道

  也叫管道,通道,go是csp管道模型进行通信

package main

import (
    "fmt"
)

//信道
//信道也是一个变量,信道运输的类型必须固定
// 重点:信道的放值和取值在默认情况下都是阻塞的
// 单向信道,即只能放或者只能取
// 关闭信道,信道关闭后就不能再放取值了 close(信道名),用rang
func test1(c chan bool)  {
    fmt.Println("hello go")
    //一旦执行完了,在信道中放入一个值  ***********++++++++++
    c <-true  //向信道中放值
}


func main() {
    //定义一个信道,关键字chan 后面跟信道类型
    //信道的空值是 nil 引用类型
    //var a chan int   //表示定义了一个int类型的信道,该信道只能运输int类型的数据
    //fmt.Println(a)

    //信道定义并初始化
    var a chan int =make(chan int)
    fmt.Println(a)
    //重点:放值和取值
    //箭头向信道变量,就是往信道中放值
    a <-1
    //箭头向外,表示从信道中取值  <-a 表示从信道取出来的值不要了(没赋值给变量)
    var b int= <-a
    fmt.Println(b)
    //信道默认情况下,取值和赋值都是阻塞的,就是一旦向信道中放入一个值,程序就卡在这里,不会继续向下执行,
    //此时必须另一个协程把它取走,程序才会继续执行,如果这个协程取,里面没有值,这个协程也会卡在这里


    //定义一个信道
    var c chan bool=make(chan bool)  //必须初始化
    go test1(c)
    //从信道中取出值,***********++++++++++
    d:=<-c
    fmt.Println(d)
    //time.Sleep(time.Second*2)

}

 用rang循环,

3,缓冲信道

  信道的本质是刚开始信道里并没有放值,所以才会阻塞,此时放是放不进去的,只有有另一个去取的时候,两者一对接,把值给它了

  缓冲信道,有缓冲大小

package main

import "fmt"

func main() {
//    缓冲信道
    //定义一个缓冲大小为3的信道
    var a chan int = make(chan int,3)
    a <-1
    a <-2
    a <-3
    //a <-4   //缓冲大小为3,只能放3个,此时超了,就会阻塞,但是程序不会一直处于阻塞,此时就报死锁错误
    <-a
    <-a  //取值
    b:=<-a
    fmt.Println("xxx")
    fmt.Println(b)  //3   如果再取就会报死锁错误
}

缓冲信道例子(协程的利用)

原文地址:https://www.cnblogs.com/Fzhiyuan/p/12046342.html