Ordinary lock Mutex and read-write lock RWMutex in Go language

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:


Figure (1) Using Mutex to simulate train ticket sales

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:


Figure (2) The main thread locks and unlocks the sub-coroutine

Guess you like

Origin blog.csdn.net/sanqima/article/details/108920558