go-mutex锁

Go语言里的Mutex和RwMutex

共享锁(S锁)又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。(多读/单写)

排他锁(X锁)又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。(单读/单写)

go里的mutex(普通锁):全局互斥锁特性(不支持同时读)----读写操作一样待遇 (类似于:只能加X锁,读写都是X锁)
sync.RWMutex:读写锁,支持单写多读特性。----读写操作不同待遇 (类似于:分两种Lock排他锁,RLock共享锁)

意思是:RWMutex是完全可以实现mutex的功能的,而RWMtex可以实现同时读。

  • func (m *Mutex) Lock()
    Lock⽅法锁住m,如果m已经加锁,则阻塞直到m解锁。
  • func (m *Mutex) Unlock()
    Unlock⽅法解锁m,如果m未加锁会导致运⾏时错误。锁和线程无关,可以由不同的线程加锁和解锁。

1.mutex无法实现分布式,多个请求怎么共享一个公共变量?

2.除非分布式请求,共享 sync.RWMutex 变量

Mutex使用

package main

import (
	"fmt"
	"sync"
	"time"
)

// 共享变量
var (
	m  sync.Mutex
	v1 int
)

// 修改共享变量
// 在Lock()和Unlock()之间的代码部分是临界区
func change(i int, m *sync.Mutex) {
	m.Lock()
	time.Sleep(time.Second)
	v1 = v1 + 1
	fmt.Printf("Write %dth time, v1:%d.\n", i, v1)
	m.Unlock()
}

func read(i int, m *sync.Mutex) {
	m.Lock()
	fmt.Printf("Read %dth time, v1:%d.\n", i, v1)
	m.Unlock()
}

func main() {
	var numGR = 10
	var wg sync.WaitGroup
	for i := 0; i < numGR; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			change(i, &m)
			read(i, &m)     //读和写都不会同时进行
		}(i)
	}
	wg.Wait()
}

RWMutex使用

package main

import (
	"fmt"
	"sync"
	"time"
)

// 共享变量
var (
	m  sync.RWMutex
	v1 int
)

// 修改共享变量
// 在Lock()和Unlock()之间的代码部分是临界区
func change(i int, m *sync.RWMutex) {
	m.Lock()
	time.Sleep(time.Second)
	v1 = v1 + 1
	fmt.Printf("Write %dth time, v1:%d.\n", i, v1)
	m.Unlock()
}

func read(i int, m *sync.RWMutex) {
	m.RLock()
	time.Sleep(time.Second)
	v1 = v1 + 1
	fmt.Printf("Read %dth time, v1:%d.\n", i, v1)
	m.RUnlock()
}

func main() {
	var numGR = 10000
	var wg sync.WaitGroup
	for i := 0; i < numGR; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
		//	change(i, &m)
			read(i, &m)
		}(i)
	}
	wg.Wait()
}

提示:并发量不高的情况下,如100,发现用共享锁获得的数据是完全没重复的,像是互斥锁的效果。但是只是并发量不高,10000并发量,共享锁的效果就提现出来了。猜测:for循环间隔时间大于自增时间了??盲猜

posted @ 2021-08-12 14:35  HexagonMan  阅读(115)  评论(0)    收藏  举报