点击打开链接
A Mutex is a mutual exclusion lock. Mutexes can be created as part of other structures; the zero value for a Mutex is an unlocked mutex.
A Mutex must not be copied after first use.
type Mutex struct {
// contains filtered or unexported fields
}
Mutex是最简单的一种锁类型,同时也比较粗暴,当一个goroutine获得了Mutex后,其他goroutine只能乖乖等待这个goroutine释放该Mutex.
func (m *Mutex) Lock()
Lock locks m. If the lock is already in use, the calling goroutine blocks until the mutex is available.
func (m *Mutex) Unlock()
Unlock unlocks m. It is a run-time error if m is not locked on entry to Unlock.
A locked Mutex is not associated with a particular goroutine. It is allowed for one goroutine to lock a Mutex and then arrange for another goroutine to unlock it.
通过调用Lock()方法对Mutex上锁,通过调用Unlock对Mutex解锁。package main
import "fmt"
import "time"
import "sync"
var mutex sync.Mutex
func f1(wg *sync.WaitGroup) {
mutex.Lock()
fmt.Println("goroutine f1 got mutex")
for i := 1; i <= 10; i++ {
fmt.Print(".")
time.Sleep(1e9)
}
fmt.Println("\ngoroutine f1 released mutex")
mutex.Unlock()
wg.Done()
}
func f2(wg *sync.WaitGroup) {
mutex.Lock()
fmt.Println("goroutine f2 got mutex")
for i := 1; i <= 10; i++ {
fmt.Print(".")
time.Sleep(1e9)
}
fmt.Println("\ngoroutine f2 released mutex")
mutex.Unlock()
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
go f1(&wg)
go f2(&wg)
wg.Wait()
fmt.Println("the main function ended.")
}运行:
C:/go/bin/go.exe run test.go [E:/project/go/lx/src]
goroutine f2 got mutex
..........
goroutine f2 released mutex
goroutine f1 got mutex
..........
goroutine f1 released mutex
the main function ended.
成功: 进程退出代码 0.
func (rw *RWMutex) Lock()
Lock locks rw for writing. If the lock is already locked for reading or writing, Lock blocks until the lock is available.
func (rw *RWMutex) RLock()
RLock locks rw for reading.
func (rw *RWMutex) RUnlock()
RUnlock undoes a single RLock call; it does not affect other simultaneous readers. It is a run-time error if rw is not locked for reading on entry to RUnlock.
func (rw *RWMutex) Unlock()
Unlock unlocks rw for writing. It is a run-time error if rw is not locked for writing on entry to Unlock.
As with Mutexes, a locked RWMutex is not associated with a particular goroutine. One goroutine may RLock (Lock) an RWMutex and then arrange for another goroutine to RUnlock (Unlock) it.
RWMutex是一种读写锁,在读锁占用的情况下,会阻止写,但不阻止读,也就是多个goroutine可同时获取读锁;在写锁被占用的情况下,会阻止任何其他的goroutine进来(不论读和写),相当于整个锁由该goroutine独占。package main
import "fmt"
import "time"
import "sync"
var rwmutex sync.RWMutex
func f1(wg *sync.WaitGroup) {
rwmutex.RLock()
fmt.Println("goroutine f1 got read lock")
for i := 1; i <= 10; i++ {
fmt.Print("f1")
time.Sleep(1e9)
}
fmt.Println("\ngoroutine f1 released read lock")
rwmutex.RUnlock()
wg.Done()
}
func f2(wg *sync.WaitGroup) {
rwmutex.RLock()
fmt.Println("goroutine f2 got read lock")
for i := 1; i <= 10; i++ {
fmt.Print("f2")
time.Sleep(1e9)
}
fmt.Println("\ngoroutine f2 released read lock")
rwmutex.RUnlock()
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
go f1(&wg)
go f2(&wg)
wg.Wait()
fmt.Println("the main function ended")
}运行:
C:/go/bin/go.exe run test2.go [E:/project/go/lx/src]
goroutine f2 got read lock
goroutine f1 got read lock
f1f2f1f2f1f2f2f1f1f2f2f1f1f2f2f1f1f2f2f1
goroutine f1 released read lock
goroutine f2 released read lock
the main function ended
成功: 进程退出代码 0.
e.g.演示RWMutex读锁和写锁相互排斥(本例先上写锁)
package main
import (
"fmt"
"sync"
"time"
)
var rwmutex sync.RWMutex
func f1(wg *sync.WaitGroup) {
rwmutex.RLock()
fmt.Println("The goroutine f1 had got the read lock")
fmt.Print("f1:")
for i := 1; i <= 10; i++ {
fmt.Print(".")
time.Sleep(1e9)
}
fmt.Println("\nThe goroutine f1 had released the read lock")
rwmutex.RUnlock()
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(1)
rwmutex.Lock()
fmt.Println("The main goroutine had got the write lock")
go f1(&wg)
fmt.Print("main:")
for i := 1; i <= 10; i++ {
fmt.Print(".")
time.Sleep(1e9)
}
fmt.Println("\nThe main goroutine had released the write lock")
rwmutex.Unlock()
wg.Wait()
fmt.Println("The main function ended.")
}
C:/go/bin/go.exe run test.go [E:/project/go/test/src]
The main goroutine had got the write lock
main:..........
The main goroutine had released the write lock
The goroutine f1 had got the read lock
f1:..........
The goroutine f1 had released the read lock
The main function ended.
成功: 进程退出代码 0.
从运行结果可以看出,其中一个goroutine获得了写锁后,其他goroutine必须等待相应的写锁被释放后,才能获得读锁。
e.g.演示RWMutex读锁和写锁相互排斥(本例先上读锁)
package main
import (
"fmt"
"sync"
"time"
)
var rwmutex sync.RWMutex
func f1(wg *sync.WaitGroup) {
rwmutex.Lock()
fmt.Println("The goroutine f1 had got the write lock")
fmt.Print("f1:")
for i := 1; i <= 10; i++ {
fmt.Print(".")
time.Sleep(1e9)
}
fmt.Println("\nThe goroutine f1 had released the write lock")
rwmutex.Unlock()
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(1)
rwmutex.RLock()
fmt.Println("The main goroutine had got the read lock")
go f1(&wg)
fmt.Print("main:")
for i := 1; i <= 10; i++ {
fmt.Print(".")
time.Sleep(1e9)
}
fmt.Println("\nThe main goroutine had released the read lock")
rwmutex.RUnlock()
wg.Wait()
fmt.Println("The main function ended.")
}
C:/go/bin/go.exe run test.go [E:/project/go/test/src]
The main goroutine had got the read lock
main:..........
The main goroutine had released the read lock
The goroutine f1 had got the write lock
f1:..........
The goroutine f1 had released the write lock
The main function ended.
成功: 进程退出代码 0.