在 go 语言中提供了并发编程模型和工具外,还提供传统的同步工具锁,包括互斥锁和读写锁
有关互斥锁有些内容我们必须清楚,也就是对于同一个互斥锁的锁定操作和解锁操作应该是成对出现。
如果一个锁定一个已经锁定的互斥锁,那么进行重复锁定操作的 goroutine 将被阻塞,直到该互斥锁回到解锁状态。
package main
import(
"fmt"
"sync"
"time"
)
func main(){
var mutex sync.Mutex
fmt.Println("Lock the lock. main groutine")
mutex.Lock()
fmt.Println("The lock is locked main groutine")
for i:= 1; i <= 3; i++{
go func(i int){
fmt.Printf("Lock the lock. (g%d)\n",i)
mutex.Lock()
fmt.Printf("The lock is locked. (g%d)\n",i)
}(i)
}
time.Sleep(time.Second)
fmt.Println("Unlock the lock. main goroutine")
mutex.Unlock()
fmt.Println("The lock is unlocked. main groutine")
time.Sleep(time.Second)
}
- 首先在 main 的 goroutine 对 mutex 进行锁定
- 然后循环创建三个 goroutine 并依次对这个已经锁定的 mutex 进行锁定
- 最后 main goroutine 中对 mutex 进行解锁,并使用 time.Sleep 让 main goroutine 在运行一段时间以便观察
Lock the lock. main groutine
The lock is locked main groutine
Lock the lock. (g3)
Lock the lock. (g1)
Lock the lock. (g2)
Unlock the lock. main goroutine
The lock is locked. main groutine
The lock is locked. (g3)
重复解锁已经锁定的锁也会引发运行时的错误。
import(
"fmt"
"sync"
)
func main() {
defer func(){
fmt.Println("try to recover the panic.")
if p := recover(); p != nil{
fmt.Printf("Recovered the panic(%#v).\n",p)
}
}()
var mutex sync.Mutex
fmt.Println("Lock the lock.")
mutex.Lock()
fmt.Println("the lock is locked")
fmt.Println("Unlock the lock")
mutex.Unlock()
fmt.Println("the lock is unlocked gain.")
fmt.Println("Unlock the lock again")
mutex.Unlock()
}
fatal error: sync: unlock of unlocked mutex
th-9.jpeg
如果想深入了解 go 语言并发编程可以阅读《go 语言并发编程实战》这本书,内容比较深。
参考 go 语言并发编程实战
网友评论