Mutex,互斥锁。

一个简单的互斥锁实现:

package main
 
import (
	"fmt"
	"sync"
)
 
func main() {
	var count = 0
	var wg sync.WaitGroup
	wg.Add(10)
 
	mu := sync.Mutex{}
 
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < 100000; j++ {
				mu.Lock()
				count++
				mu.Unlock()
			}
		}()
	}
 
	wg.Wait()
 
	fmt.Println(count)
}
 

下面是一个复杂的但是很经典的升级版实现。将 Mutex 藏在 结构体和 func 函数里。

package main
 
import (
	"fmt"
	"sync"
)
 
type Counter struct {
	CounterType int
	Name        string
	mu          sync.Mutex
	count       uint64
}
 
// Inc 递增函数,内部使用互斥锁保护
func (c *Counter) Inc() {
	c.mu.Lock()
	c.count++
	c.mu.Unlock()
}
 
// Count得到计数器的值,也许要锁保护
func (c *Counter) Count() uint64 {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.count
}
 
func main() {
	var counter Counter
	var wg sync.WaitGroup
	wg.Add(10)
 
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < 100000; j++ {
				counter.Inc()
			}
		}()
	}
 
	wg.Wait()
 
	fmt.Println(counter.Count())
}
 

如果读操作多余写操作

使用 sync.RWMutex。允许多个 goroutine 同时读取计数器的值,但是只允许一个 goroutine 写入。

package main
 
import (
	"fmt"
	"sync"
)
 
type Counter struct {
	CounterType int
	Name        string
	mu          sync.RWMutex
	count       uint64
}
 
func (c *Counter) Inc() {
	c.mu.Lock()
	c.count++
	c.mu.Unlock()
}
 
func (c *Counter) Count() uint64 {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.count
}
 
func main() {
	var counter Counter
	var wg sync.WaitGroup
	wg.Add(10)
 
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
 
			for i := 0; i < 100000; i++ {
				counter.Inc()
			}
		}()
	}
 
	wg.Wait()
	fmt.Println(counter.Count())
}