1. Mutex de bloqueio comum
1.1 Protótipo
tipo Mutex struct { state int32 sema uint32 }
- Mutex é um bloqueio mutex que pode ser criado como um campo de outras estruturas; o valor zero é desbloqueado. Os bloqueios do tipo Mutex não estão relacionados a threads e podem ser bloqueados e desbloqueados por threads diferentes.
1.2 Métodos em Mutex
- função (m * Mutex) Lock ()
Lock método locks m, se m já estiver bloqueado, ele irá bloquear até que m seja desbloqueado. - função (m * Mutex) Unlock ()
Método de desbloqueio desbloqueia m. Se m não estiver bloqueado, causará erro de tempo de execução. Os bloqueios não têm nada a ver com threads e podem ser bloqueados e desbloqueados por diferentes threads.
Caso 1. Use cadeados comuns para vender bilhetes nas estações de trem
//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("所有车票已售空,程序结束!")
}
O efeito é o seguinte:
Dois, bloqueio de leitura e gravação RWMutex
2.1 Protótipo
tipo RWMutex struct { w Mutex writerSem uint32 readerSem uint32 readerCount int32 readerWait int32 }
- RWMutex é um bloqueio mutex de leitura e gravação. O bloqueio pode ser realizado por vários leitores ao mesmo tempo ou por apenas um escritor. RWMutex pode ser criado como um campo de outras estruturas; o valor zero é desbloqueado. Os bloqueios do tipo RWMutex também são independentes de threads. Diferentes threads podem adicionar bloqueio de leitura / gravação e desbloquear bloqueios de leitura / gravação.
- Regras de bloqueio:
a) No uso de bloqueios de leitura e gravação: as operações de gravação são mutuamente exclusivas, a leitura e a gravação são mutuamente exclusivas e a leitura e a leitura não são mutuamente exclusivas.
b) pode ser uma pluralidade de goroutine ler simultaneamente os dados , mas só permite uma ⼀ goroutine gravar dados .
2.2 Métodos em RWMutex
- func (rw * RWMutex) Lock () O
método de bloqueio bloqueia rw para escrever o estado, proibindo outras threads de ler ou escrever. - func (rw * RWMutex) Unlock () O
método de desbloqueio desbloqueia o estado de bloqueio de gravação de rw. Se m não estiver bloqueado, ele causará um erro de tempo de execução. - func (rw * RWMutex) RLock () O
método RLock bloqueia rw em um estado de leitura, proíbe outras threads de escrever, mas não pode evitar a leitura. - func (rw * RWMutex) RUnlock ()
O método Runlock libera o status de bloqueio de leitura de rw. Se m não adicionar bloqueio de leitura, ele causará um erro de tempo de execução. - func (rw * RWMutex) RLocker () Locker O
método Rlocker retorna um bloqueio de exclusão mútua.A interface Locker é realizada chamando rw.Rlock e rw.Runlock.
Caso 2. O thread principal bloqueia e desbloqueia a subcorrotina
//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 写解锁...")
}
O efeito é o seguinte: