1. Bloqueo ordinario Mutex
1.1 Prototipo
escriba Mutex struct { state int32 sema uint32 }
- Mutex es un bloqueo mutex que se puede crear como un campo de otras estructuras; el valor cero está desbloqueado. Los bloqueos de tipo mutex no están relacionados con subprocesos y pueden bloquearse y desbloquearse mediante diferentes subprocesos.
1.2 Métodos en Mutex
- func (m * Mutex) Lock () El
método de bloqueo bloquea m, si m ya está bloqueado, se bloqueará hasta que m se desbloquee. - func (m * Mutex) Unlock () El
método de desbloqueo desbloquea m.Si m no está bloqueado, provocará un error de tiempo de ejecución. Los bloqueos no tienen nada que ver con los hilos y pueden bloquearse y desbloquearse mediante distintos hilos.
Caso 1. Use candados comunes para vender boletos en las estaciones de tren
//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("所有车票已售空,程序结束!")
}
El efecto es el siguiente:
Dos, bloqueo de lectura y escritura RWMutex
2.1 Prototipo
escriba RWMutex struct { w Mutex writerSem uint32 readerSem uint32 readerCount int32 readerWait int32 }
- RWMutex es un bloqueo mutex de lectura-escritura. El bloqueo puede ser mantenido por varios lectores al mismo tiempo o por un solo escritor. RWMutex se puede crear como un campo de otras estructuras; el valor cero está desbloqueado. Los bloqueos de tipo RWMutex también son independientes de los subprocesos. Diferentes subprocesos pueden agregar bloqueo de lectura / escritura y desbloquear bloqueos de lectura / escritura.
- Reglas de bloqueo:
a) En el uso de bloqueos de lectura-escritura: las operaciones de escritura son mutuamente excluyentes, lectura y escritura son mutuamente excluyentes y lectura y lectura no son mutuamente excluyentes.
b) puede haber una pluralidad de goroutine que lean simultáneamente los datos , pero solo permite una ⼀ goroutine escribir datos .
2.2 Métodos en RWMutex
- func (rw * RWMutex) Lock () El
método de bloqueo bloquea rw en el estado de escritura, prohibiendo que otros hilos lean o escriban. - func (rw * RWMutex) Unlock () El
método de desbloqueo desbloquea el estado de bloqueo de escritura de rw.Si m no está bloqueado, provocará un error de tiempo de ejecución. - func (rw * RWMutex) RLock () El
método RLock bloquea rw en un estado de lectura, prohíbe que otros subprocesos escriban, pero no puede ayudar a leer. - func (rw * RWMutex) RUnlock ()
El método Runlock libera el estado de bloqueo de lectura de rw. Si m no agrega bloqueo de lectura, causará un error de tiempo de ejecución. - func (rw * RWMutex) RLocker () Locker El
método Rlocker devuelve un bloqueo de exclusión mutua La interfaz de Locker se realiza llamando a rw.Rlock y rw.Runlock.
Caso 2. El hilo principal bloquea y desbloquea la subcorutina
//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 写解锁...")
}
El efecto es el siguiente: