Bloqueio comum Mutex e bloqueio de leitura e gravação RWMutex na linguagem Go

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:


Figura (1) Usando Mutex para simular vendas de passagens de trem

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:


Figura (2) O thread principal bloqueia e desbloqueia a sub-co-rotina

Acho que você gosta

Origin blog.csdn.net/sanqima/article/details/108920558
Recomendado
Clasificación