0
点赞
收藏
分享

微信扫一扫

golang知识点

爪哇驿站 2022-02-27 阅读 105

1、channel是一个指针

slice和map

makemap 和 makeslice 的区别,带来一个不同点:当 map 和 slice 作为函数参数时,在函数参数内部对 map 的操作会影响 map 自身;而对 slice 却不会
主要原因:一个是指针( *hmap),一个是结构体( slice)。Go 语言中的函数传参都是值传递,在函数内部,参数会被 copy 到本地。*hmap指针 copy 完之后,仍然指向同一个 map,因此函数内部对 map 的操作会影响实参。而 slice 被 copy 后,会成为一个新的 slice,对它进行的操作不会影响到实参。
但是操作slice中的数组会影响数据,因为新的slice仍然是指向同个数组

GMP

  1. 如果g进入了系统调用状态,那么与其绑定的M也将进入系统调用状态

struct 比较

相同类型的struct:
含有map、slice等不可比较的属性 则 struct不可以比较,==编译通不过
若所有属性都可以比较,那么可以比较

不同类型的struct:
若符合↑,强转后可以比较

reflect.DeepEqual ptr1==ptr2 || 所有的变量相等

defer

延迟执行语句,在所属的函数退出之前,按defer的逆序进行执行

(close关闭一个无缓冲的通道,会让其由阻塞变为不断读出0值的通道?)

context包

谷歌官方开发的,用于对一个请求衍生出来的各个goroutine施加约束。比如context传递给多个goroutine使用时,执行一次cancel就可以取消所有的goroutine。

协程同步

select +chan
waitGroup
context

什么是goroutine chan

goroutine 是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理。Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU。

goroutine 是 Go语言程序的并发体的话,那么 channels 就是它们之间的通信机制。它可以让一个 goroutine 通过它给另一个 goroutine 发送值信息。

chan:

  1. 关闭的chan进行写操作会panic,读操作会返回类型零值和false
  2. 单方向通道不可以隐式转换为普通通道,反之可以
  3. 通道数据结构hchan是数组和下标指针模拟环形队列、读写等待协程链表
  4. chan写入:
    1、读等待协程链表有协程那么直接获取第一个等待读数据的协程,并把数据复制到那个协程并唤醒他
    2、没有等待的读协程,环形缓冲队列还有位置
    3、缓冲队列没有位置那么将当前协程加入写等待协程链表

select

  1. select和switch类似,但是每个case都是一个通道读写
  2. 多个case的通道准备好数据时,随机选择一个
  3. 只有一个case的时候,编译器会优化去掉select
  4. 两轮循环,第一轮循环检查是否有准备好的case,或者default,没有的话第二轮循环创建一个sudog结构体,放入所有case中的读写通道的读写等待协程链表后面,并阻塞当前线程。当任意一个case不再阻塞,唤醒当前协程,并取消当前协程的sudog挂在其他case中的通道的等待链表

race是通过谷歌开发的Threadsantinizer检测的,本来是检测C++的数据争用问题,go中通过GOC调用

自旋锁

获取到锁才操作,没有获取到就一直循环等待锁

mutex互斥锁

结构体 m{state int32 , sema uint32}
高29位是当前互斥锁上等待的goroutine个数
饥饿状态位,唤醒状态位,锁定状态位 低三位

加锁过程

原子CAS操作加锁,如果发现锁定状态位为1,那么进入慢加锁过程

  1. 如果是非饥饿模式,且满足(多核多P,当前P本地队列无其他协程,自旋次数小于4)则先自旋获取锁,30次pause
  2. 如果长时间未获取到锁那么开始用信号量同步

。。。

读写锁

读写锁复用了互斥锁,写锁只能有一个,需要互斥获取
type RWMutex struct{
w Mutex
writerSem uint32
readerSem uint32
readerCount int32
readerWait int32
}

写锁加锁
获取互斥锁,减去一个很大的数,表示有写锁
在这里插入图片描述
获取互斥锁之后,将readerCount 减去1<<30 ,为了告诉reader在尝试加写锁或者已经有写锁,因为一般的readerCount在增加读者时,也就几个几十个,释放读锁时,readerCount原子操作减一,最小为0。
r表示原来的readerCount,将其赋值给readerWait表示阻塞的写锁等待这么多的读者退出
然后对writerSem信号量p操作阻塞住

读锁加锁
在这里插入图片描述
读锁可以加很多把,根据上面的写锁,当有写锁在准备加或者已经有写锁时,阻塞当前协程,在readerSem上进行p操作

读锁释放
readerCount原子操作减一,若结果是负数,说明有写锁等待或者有写锁,那么尝试对readerWait(加写锁时还有的读者数量)减一,恰好是最后一个读者,那么对writerSem进行V操作,唤醒欲加写锁的协程。

写锁释放
将readerCount+那个很大的数,结果为r,在写锁期间,有r个协程阻塞,对readerSem 进行r次V操作,依次唤醒。

举报

相关推荐

0 条评论