Skip to content

Instantly share code, notes, and snippets.

@z1076
Last active August 21, 2021 09:24
Show Gist options
  • Save z1076/e56c60f88e02f322b83cbd479ba1d3ee to your computer and use it in GitHub Desktop.
Save z1076/e56c60f88e02f322b83cbd479ba1d3ee to your computer and use it in GitHub Desktop.
[Golang 锁机制] #协程
//互斥锁
//互斥即不可同时运行。即使用了互斥锁的两个代码片段互相排斥,只有其中一个代码片段执行完成后,另一个才能执行。
//互斥锁是传统的并发程序对共享资源进行访问控制的主要手段,在 Go 中,似乎更推崇由 channel 来实现资源共享和通信。它由标准库代码包 sync 中的 Mutex 结构体类型代表。只有两个公开方法:调用 Lock()获得锁,调用 unlock()释放锁。
/**
https://learnku.com/go/t/32513
使用 Lock () 加锁后,不能再继续对其加锁(同一个 goroutine 中,即:同步调用),否则会 panic。只有在 unlock () 之后才能再次 Lock ()。异步调用 Lock (),是正当的锁竞争,当然不会有 panic 了。适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁也叫做全局锁。
func (m *Mutex) Unlock () 用于解锁 m,如果在使用 Unlock () 前未加锁,就会引起一个运行错误。已经锁定的 Mutex 并不与特定的 goroutine 相关联,这样可以利用一个 goroutine 对其加锁,再利用其他 goroutine 对其解锁。
**/
//lck.Lock () 会阻塞直到获取锁,然后利用 defer 语句在函数返回时自动释放锁。
var lck sync.Mutex
func foo() {
lck.Lock()
defer lck.Unlock()
// ...
}
// 对象加锁
type Accout struct {
flag sync.Mutex //sync.Mutex类型
}
//进行读的操作
func (a *Accout) Reed(n int) { //读
a.flag.Lock() //锁上
defer a.flag.Unlock() //在方法运行完之后解开
}
//进行写的操作
func (a *Accout) Write(n int) { //读
a.flag.Lock() //锁上
defer a.flag.Unlock() //在方法运行完之后解开
}
//读写锁
//读写锁的存在是为了解决读多写少时的性能问题,读场景较多时,读写锁可有效地减少锁阻塞的时间。
type RWLock struct {
count int
mu sync.RWMutex
}
func (l *RWLock) Write() {
l.mu.Lock()
l.count++
time.Sleep(cost)
l.mu.Unlock()
}
func (l *RWLock) Read() {
l.mu.RLock()
_ = l.count
time.Sleep(cost)
l.mu.RUnlock()
}
// 一般用来控制协程执行顺序
package main
import "sync"
var wg sync.WaitGroup
func main() {
for i := 0; i < 10; i++ {
wg.Add(1) // 计数+1
go func() {
println("1")
wg.Done() // 计数-1,相当于wg.add(-1)
}()
}
wg.Wait() // 阻塞带等待所有协程执行完毕
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment