1. Ordinary lock Mutex
1.1 Prototype
type Mutex struct {
state int32
sema uint32
}
- Mutex is a mutex lock that can be created as a field of other structures; zero value is unlocked. Mutex type locks are not related to threads, and can be locked and unlocked by different threads.
1.2 Methods in Mutex
- func (m *Mutex) Lock()
Lock method locks m, if m is already locked, it will block until m is unlocked. - func (m *Mutex) Unlock()
Unlock method unlocks m. If m is not locked, it will cause a runtime error. Locks have nothing to do with threads, and can be locked and unlocked by different threads.
Case 1. Use ordinary locks to sell tickets at train stations
//myMutexTick.go
// myMutexDes project main.go
package main
import (
"fmt"
"sync"
"time"
)
//全局变量
var ticks = 100
var wg sync.WaitGroup
var mutex sync.Mutex
func saleTickets(name string, wg *sync.WaitGroup) {
for {
mutex.Lock()
if ticks > 0 {
time.Sleep(200 * time.Microsecond)
fmt.Println(name, ": ", ticks)
ticks--
} else {
fmt.Println(name, "结束卖票...")
mutex.Unlock()
break
}
mutex.Unlock()
}
wg.Done() //通知计数器减一
}
func main() {
//模拟火车站卖票
//火车票一共100张,4个售票口出售(相当于4个子协程)
var wg sync.WaitGroup
wg.Add(4)
go saleTickets("售票口A ", &wg)
go saleTickets("售票口B ", &wg)
go saleTickets("售票口C ", &wg)
go saleTickets("售票口D ", &wg)
wg.Wait()
fmt.Println("所有车票已售空,程序结束!")
}
The effect is as follows:
Two, read-write lock RWMutex
2.1 Prototype
type RWMutex struct {
w Mutex
writerSem uint32
readerSem uint32
readerCount int32
readerWait int32
}
- RWMutex is a read-write mutex lock. The lock can be held by multiple readers at the same time or by only one writer. RWMutex can be created as a field of other structures; zero value is unlocked. RWMutex type locks are also independent of threads. Different threads can add read lock/write and unlock read/write locks.
- Locking rules:
a) In the use of read-write locks: write operations are mutually exclusive, read and write are mutually exclusive, and read and read are not mutually exclusive.
b) may be a plurality of goroutine simultaneously read the data , but only allows a ⼀ goroutine write data .
2.2 Methods in RWMutex
- func (rw *RWMutex) Lock()
Lock method locks rw into writing state, prohibiting other threads from reading or writing. - func (rw *RWMutex) Unlock()
Unlock method unlocks the write lock state of rw. If m is not locked, it will cause a runtime error. - func (rw *RWMutex) RLock() The
RLock method locks rw into a read state, prohibits other threads from writing, but cannot help reading. - func (rw *RWMutex) RUnlock()
Runlock method releases the read lock status of rw. If m does not add read lock, it will cause a runtime error. - func (rw *RWMutex) RLocker() Locker The
Rlocker method returns a mutual exclusion lock and implements the Locker interface by calling rw.Rlock and rw.Runlock.
Case 2. The main thread locks and unlocks the sub-coroutine
//myMutexWrite.go
// myMutexWrite project main.go
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var rwm sync.RWMutex
for i := 1; i <= 3; i++ {
go func(i int) {
fmt.Printf("goroutine %d, 尝试读锁定", i)
rwm.RLock()
fmt.Printf("goroutine %d, 已经读锁定了...\n", i)
time.Sleep(3 * time.Second)
fmt.Printf("goroutine %d, 读解锁...\n", i)
rwm.RUnlock()
}(i)
}
time.Sleep(1 * time.Second)
fmt.Println("main 尝试写锁定...")
rwm.Lock()
fmt.Println("main 已经写锁定了...")
rwm.Unlock()
fmt.Printf("main 写解锁...")
}
The effect is as follows: