Go 专栏|并发编程:goroutine,channel 和 sync,一招彻底弄懂

func main() {

ch := make(chan int)

for i := 0; i < 10; i++ {

go Add(i, i, ch)

}

for i := 0; i < 10; i++ {

fmt.Println(<-ch)

}

}

可以正常输出结果。

主 goroutine 会阻塞,直到读取到通道中的值,程序继续执行,最后退出。

缓冲 channel

创建一个容量是 5 的缓冲通道:

ch := make(chan int, 5)

缓冲通道的发送操作在通道尾部插入一个元素,接收操作从通道的头部移除一个元素。如果通道满了,发送会阻塞,直到另一个 goroutine 执行接收。相反,如果通道是空的,接收会阻塞,直到另一个 goroutine 执行发送。

有没有感觉,其实缓冲通道和队列一样,把操作都解耦了。

单向 channel

类型 chan<- int 是一个只能发送的通道,类型 <-chan int 是一个只能接收的通道。

任何双向通道都可以用作单向通道,但反过来不行。

还有一点需要注意,close 只能用在发送通道上,如果用在接收通道会报错。

看一个单向通道的例子:

package main

import “fmt”

func counter(out chan<- int) {

for x := 0; x < 10; x++ {

out <- x

}

close(out)

}

func squarer(out chan<- int, in <-chan int) {

for v := range in {

out <- v * v

}

close(out)

}

func printer(in <-chan int) {

for v := range in {

fmt.Println(v)

}

}

func main() {

n := make(chan int)

s := make(chan int)

go counter(n)

go squarer(s, n)

printer(s)

}

sync

sync 包提供了两种锁类型:sync.Mutexsync.RWMutex,前者是互斥锁,后者是读写锁。

当一个 goroutine 获取了 Mutex 后,其他 goroutine 不管读写,只能等待,直到锁被释放。

package main

import (

“fmt”

“sync”

“time”

)

func main() {

var mutex sync.Mutex

wg := sync.WaitGroup{}

// 主 goroutine 先获取锁

fmt.Println(“Locking (G0)”)

mutex.Lock()

fmt.Println(“locked (G0)”)

wg.Add(3)

for i := 1; i < 4; i++ {

go func(i int) {

// 由于主 goroutine 先获取锁,程序开始 5 秒会阻塞在这里

fmt.Printf(“Locking (G%d)\n”, i)

mutex.Lock()

fmt.Printf(“locked (G%d)\n”, i)

time.Sleep(time.Second * 2)

mutex.Unlock()

fmt.Printf(“unlocked (G%d)\n”, i)

wg.Done()

}(i)

}

// 主 goroutine 5 秒后释放锁

time.Sleep(time.Second * 5)

fmt.Println(“ready unlock (G0)”)

mutex.Unlock()

fmt.Println(“unlocked (G0)”)

wg.Wait()

}

RWMutex 属于经典的单写多读模型,当读锁被占用时,会阻止写,但不阻止读。而写锁会阻止写和读。

package main

import (

“fmt”

“sync”

“time”

)

func main() {

var rwMutex sync.RWMutex

wg := sync.WaitGroup{}

Data := 0

wg.Add(20)

for i := 0; i < 10; i++ {

go func(t int) {

// 第一次运行后,写解锁。

// 循环到第二次时,读锁定后,goroutine 没有阻塞,同时读成功。

fmt.Println(“Locking”)

rwMutex.RLock()

defer rwMutex.RUnlock()

fmt.Printf(“Read data: %v\n”, Data)

wg.Done()

time.Sleep(2 * time.Second)

}(i)

go func(t int) {

// 写锁定下是需要解锁后才能写的

rwMutex.Lock()

defer rwMutex.Unlock()

Data += t

fmt.Printf(“Write Data: %v %d \n”, Data, t)

wg.Done()

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
img

1c05e862fe4e9.png)

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
[外链图片转存中…(img-T7qJV8cD-1711653239643)]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值