go基本语法学习笔记之并发编程

  GO并发

 在一个函数调用前加上go关键字,这次调用就会在一个新的goroutine中并发执行。

func Add(x, y int) {
     z := x + y
     fmt.Println(z)
}
func main() {
    for i := 0; i < 10; i++ {
            go Add(i, i)
    }
}


     Go程序从初始化main package并执行main()函数开始,当main()函数返回时,程序退出.且程序并不等待

其他goroutine(非主goroutine)结束。

并发通信

GO语言既以并发编程作为语言的最核心优势,提供了一种通信模型,即以消息机制而非共享内存作为通信方式。
消息机制认为每个并发单元是自包含的、独立的个体,并且都有自己的变量,但在不同并发单元间这些变量不共享。每个并发单元的输入和输出只有一种,那就是消息。
这有点类似于进程的概念,每个进程不会被其他进程打扰,它只做好自己的工作就可以了。不同进程间靠消息来通信,它们不会共享内存。

Go语言提供的消息通信机制被称为channel
       “不要通过共享内存来通信,而应该通过通信来共享内存。”

channel

channel是Go语言在语言级别提供的goroutine间的通信方式。channel是类型相关的

chan声明

var chanName chan ElementType
如:
var chint chan int  //什么一个int类型的chan

var mch  map[string] chan bool  //声明一个map,其元素为bool

var arrch [10]chan int //定义一个

实例

func Count(ch chan int) {
     ch <- 1
     fmt.Println("Counting")
}
func main() {
     chs := make([]chan int, 10)
     for i := 0; i < 10; i++ {
         chs[i] = make(chan int)
         go Count(chs[i])
     }
     for _, ch := range(chs) {
         <-ch
     }
}
定义channel
直接使用内置的函数make()即可:
    ch := make(chan int)
channel基本用法
写入
<span style="white-space:pre">	</span>ch < 1
向channel写入数据通常会导致程序阻塞,直到有其他goroutine从这个channel中读取数据

读出
   i := < ch
如果ch没有数据也会导致程序阻塞,直到有数据写入ch

但是,对ch的阻塞,可以利用ch的缓冲机制以及select来灵活出来

缓冲机制
带缓冲的channel适合于需连续传输大量数据的场景,定义一个带缓冲的channel,只需将容量传入make的第二个参数即可
   c := make(chan int, 1024)  //创建了一个大小为1024的整形chan,写入在缓冲区满前 不会阻塞
channel是可传递的

单向channel
单向channel只能用于发送或者接收数据。
声明
var ch1 chan int // ch1是一个正常的channel,不是单向的
var ch2 chan<- float64// ch2是单向channel,只用于写float64数据
var ch3 <-chan int // ch3是单向channel,只用于读取int数据
初始化
channel可以 在单向channel和双向channel之间进行转换,channel本身就是GO的原生类型,因此可被传递,也可类型转换
ch4 := make(chan int)
ch5 := <-chan int(ch4) // ch5就是一个单向的读取channel
ch6 := chan<- int(ch4) // ch6 是一个单向的写入channel
关闭channel
直接用 close即可
close(ch)
判断channel是否已关闭,可以用多值返回读,如果第二个bool返回值是false则表示ch已经被关闭
x, ok := <-ch

select

用来监控一系列文件句柄发生的IO操作,一旦有其中一个句柄发生IO操作,则被返回
GO在语言级别支持select
代码结构大致如:
select {
<span style="white-space:pre">	</span>case <-chan1:
<span style="white-space:pre">	</span>// 如果chan1成功读到数据,则进行该case处理语句
<span style="white-space:pre">	</span>case chan2 <- 1:
<span style="white-space:pre">	</span>// 如果成功向chan2写入数据,则进行该case处理语句
<span style="white-space:pre">	</span>default:
<span style="white-space:pre">	</span>// 如果上面都没有成功,则进入default处理流程
}
其中每个case必须是一个文件句柄操作
结合for可实现循环检测
ch := make(chan int, 1)
for {
<span style="white-space:pre">	</span>select {
<span style="white-space:pre">		</span>case ch <- 0:
<span style="white-space:pre">		</span>case ch <- 1:
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>i := <-ch
<span style="white-space:pre">	</span>fmt.Println("Value received:", i)
}






























  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值