go语言自学笔记(三)


goroutine

开启一个协程执行这个函数
go func()

main 的地位相当于主协程,当 main 函数执行完成后,主协程终结,其下的运行着的所有协程也立即退出。
可以使用 time.Sleep 来使 main 阻塞,使其他协程能够有机会运行完全。

channel

信道名 := make(chan 信道类型)

信道是一种队列式的数据结构,遵循先入先出的规则,是连接多个goroutine程序的管道 。
发送和接收两个操作都是用<-运算符。

ch <- x // 发送给信道
x = <-ch // 从信道接受
<-ch // 接受

信道死锁
1.当信道里的数据量等于信道的容量后,此时再往信道里发送数据,就失造成阻塞。

2.当程序一直在等待从信道里读取数据,当不再往信道中写入数据时程序就会陷入死循环。因此在发送完数据后,要手动关闭信道。
关闭信道:close(信道名)

判断信道是否被关闭:x, ok := <-信道名
如果已经被关闭,ok 为 false,若还没被关闭,ok 为true。

select函数
select 语句用于在多个发送/接收信道操作中进行选择。

select {    
        case 1 := <-信道:
            
        case 2 := <-信道:
      
       default:
    }
}

当 select 由多个 case 准备就绪时,将会随机地选取其中之一去执行。只要有一个信道有接收到数据,那么 select 就结束。

缓冲与无缓冲

无缓冲信道
对于无缓冲信道,在接收者未准备好之前,发送操作是阻塞的。
解决方法:
1.使接收者代码在发送者之前执行
注意将接收者代码写在另一个协程里

2.使用缓冲信道

缓冲信道
信道名:= make(chan 信道类型, 信道容量)

信道的容量,可以使用 cap 函数获取 ;信道的长度,可以使用 len 长度获取。

单向与双向

双向通道
通道默认双向

单向通道
分为 只读信道 和 只写信道。
只读 <-chan 表示这个信道只能从里发出数据

var pipline = make(chan int)
type Receiver = <-chan int 
var r Receiver = pipline

只写 chan<- 表示这个信道只能从外面接收数据

waitgroup

要想保证 main goroutine 在所有的 goroutine 都执行完毕后再退出,可以使用信道来标记完成 :
定义一个信道,在任务完成后,往信道中写入true,当在主协程中获取到true,就认为子协程已经执行完毕。

也可以用 sync包 提供的 WaitGroup类型(结构体类型) :
var 实例名 sync.WaitGroup

Add:初始值为0,你传入的值会往计数器上加,这里直接传入你子协程的数量
Done:当某个子协程完成后,可调用此方法,会从计数器上减一,通常可以使用 defer 来调用。
Wait:阻塞当前协程,直到实例里的计数器归零。

锁机制

互斥锁

Mutex可以保护临界区,防止竞争条件,用来保证在任一时刻,只能有一个线程访问该对象。

定义方式:
var 名 *sync.Mutex
名 = new(sync.Mutex)

名 := &sync.Mutex{}

加锁 名.Lock()
解锁 名.Unlock()

在Lock和Unlock之间的代码段中的内容goroutine可以随便读取或者修改,这个代码段叫做临界区。

读写锁

RWMutex将程序对资源的访问分为读操作和写操作
读锁占用时,写锁会阻塞
允许多个 只读操作并行执行,但写操作会完全互斥。

var lock *sync.RWMutex
lock = new(sync.RWMutex)


lock := &sync.RWMutex{}

读锁:调用 RLock 方法开启锁,调用 RUnlock 释放锁
写锁:调用 Lock 方法开启锁,调用 Unlock 释放锁

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值