Golang – Mutex和RwMutex区别
Mutex
和 RWMutex
都是用于控制并发访问共享资源的两种锁。
Mutex
是最简单的锁,确保同一时间只有一个goroutine能读取或写入共享资源。RwMutex
是一种读写锁,可以自定义读或写添加锁,所以相比Mutex灵活度比较高,而且如果你的program读多写少的情况下,只对于写入加锁的话,那么效率肯定会比较Mutex来得更高
数据竞争: 在并发环境下,如果不对共享资源进行适当的锁定,就会导致数据竞争,产生不一致和不准确的结果。
重要性: 使用锁(无论是互斥锁 Mutex
还是读写锁 RWMutex
)来保护共享资源,对于确保数据一致性和程序正确性是至关重要的。
Mutex代码范例:
var mu sync.Mutex
mu.Lock() //获取锁,如果锁已经被其他Goroutine持有,则调用的Goroutine会被阻塞直到锁被释放。
// 临界区代码
mu.Unlock() //释放锁,使其他被阻塞的Goroutine有机会获取锁。
RwMutex代码范例:
var rwMu sync.RWMutex
rwMu.RLock()
//获取读锁,如果有其他写锁持有者,调用的Goroutine会被阻塞。可以同时有多个Goroutine持有读锁。
// 读操作
rwMu.RUnlock() //释放读锁。
rwMu.Lock() //获取写锁,如果有其他读锁或写锁持有者,调用的Goroutine会被阻塞,写锁是排他性的。
// 写操作
rwMu.Unlock() //释放写锁。
RwMutex 读写都加锁的使用案例:
type Counter struct {
value int
mu sync.RWMutex
}
func (c *Counter) Increment() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func (c *Counter) Value() int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.value
}
func main() {
counter := Counter{}
var wg sync.WaitGroup
// 启动10个goroutine来读取计数器值
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("Goroutine %d reads counter value: %d\n", id, counter.Value())
time.Sleep(100 * time.Millisecond)
}(i)
}
// 启动1个goroutine来增加计数器值
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 5; i++ {
counter.increment()
fmt.Printf("Counter incremented to: %d\n", counter.value())
time.sleep(150 * time.Millisecond)
}
}()
// 等待所有goroutine完成
wg.Wait()
fmt.Printf("Final counter value: %d\n", counter.Value())
}
/*
输出结果:
Goroutine 0 reads counter value: 0
Goroutine 1 reads counter value: 0
Goroutine 2 reads counter value: 0
Goroutine 3 reads counter value: 0
Goroutine 4 reads counter value: 0
Goroutine 5 reads counter value: 0
Goroutine 6 reads counter value: 0
Goroutine 7 reads counter value: 0
Goroutine 8 reads counter value: 0
Goroutine 9 reads counter value: 0
Counter incremented to: 1
Counter incremented to: 2
Counter incremented to: 3
Counter incremented to: 4
Counter incremented to: 5
Final counter value: 5
*/
RwMutex 读不加锁,只对写加锁的使用案例:
type Counter struct {
value int
mu sync.Mutex // 这里只使用Mutex,而不使用RWMutex
}
func (c *Counter) Increment() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func (c *Counter) Value() int {
// 去掉了RLock和RUnlock,直接读取值
return c.value
}
func main() {
counter := Counter{}
var wg sync.WaitGroup
// 启动10个goroutine来读取计数器值
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("Goroutine %d reads counter value: %d\n", id, counter.Value())
time.Sleep(100 * time.Millisecond)
}(i)
}
// 启动1个goroutine来增加计数器值
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 5; i++ {
counter.Increment()
fmt.Printf("Counter incremented to: %d\n", counter.Value())
time.Sleep(150 * time.Millisecond)
}
}()
// 等待所有goroutine完成
wg.Wait()
fmt.Printf("Final counter value: %d\n", counter.Value())
}
/*
输出结果:
Goroutine 0 reads counter value: 0
Goroutine 1 reads counter value: 0
Goroutine 2 reads counter value: 1
Goroutine 3 reads counter value: 1
Counter incremented to: 2
Counter incremented to: 3
Counter incremented to: 4
Goroutine 4 reads counter value: 3
Goroutine 5 reads counter value: 4
Counter incremented to: 5
Goroutine 6 reads counter value: 5
Goroutine 7 reads counter value: 5
Goroutine 8 reads counter value: 5
Goroutine 9 reads counter value: 5
Final counter value: 5
*/
Facebook评论