Once 对象用来确保只执行一次的处理场景,注意这里的一次只是对于单个进程,且这个Once对象没有被复制的情况,在分布式的应用中,这个对象可能并不适用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func TestOnce (f *testing.T) { var once sync.Once onceBody := func () { fmt.Println("Only once" ) } done := make (chan bool ) for i := 0 ; i < 10 ; i++ { go func () { once.Do(onceBody) done <- true }() } for i := 0 ; i < 10 ; i++ { <-done } }
Pool 对象池,用来生成以及缓存对象,如果池子里没有对象,则会调用New方法创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 func TestPool (f *testing.T) { var pool = sync.Pool{ New: func () interface {} { return bytes.NewBuffer([]byte ("init:" )) }, } buff := pool.Get().(*bytes.Buffer) buff.Write([]byte ("one" )) fmt.Println(buff.String()) pool.Put(bytes.NewBuffer([]byte ("two" ))) buff2 := pool.Get().(*bytes.Buffer) fmt.Println(buff2.String()) }
打印结果
Map Map对象和 map[interface{}]interface{} 类似,只不过Map是线程安全的,并且提供了一些增删改查的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 func TestMap (f *testing.T) { var mp sync.Map mp.Store("name" , "jack" ) mp.Store("age" , "20" ) v, ok := mp.Load("name" ) if ok { fmt.Println(v) } mp.Range(func (key, value interface {}) bool { fmt.Println(key, value) return true }) }
其中Range方法,用于遍历map,如果返回false,则终止遍历
Mutex Mutex 互斥锁,用来保证同一时间不能有多个并发协程访问某一个资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 type Wallet struct { Amount float64 lock sync.Mutex }func (w *Wallet) Increase() { if w.lock.TryLock() { w.Amount += 1 w.lock.Unlock() } }func (w *Wallet) Decrease() { if w.lock.TryLock() { w.Amount -= 1 w.lock.Unlock() } }
RWMutex RWMutex 读写锁,多个并发协程同时读取某一个资源,但只有一个并发协程能够更新资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 type Bank struct { sync.RWMutex balance map [string ]float64 }func (b *Bank) In(account string , value float64 ) { b.Lock() defer b.Unlock() v, ok := b.balance[account] if !ok { b.balance[account] = 0.0 } b.balance[account] += v }func (b *Bank) Out(account string , value float64 ) error { b.Lock() defer b.Unlock() v, ok := b.balance[account] if !ok || v < value { return errors.New("account not enough balance" ) } b.balance[account] -= value return nil }func (b *Bank) Query(account string ) float64 { b.RLock() defer b.RUnlock() v, ok := b.balance[account] if !ok { return 0.0 } return v }
WaitGroup 等待组,场景多用于等待多个任务都处理完成之后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 type httpPkg struct {}func (httpPkg) Get(url string ) {}var http httpPkgfunc main () { var wg sync.WaitGroup var urls = []string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } for _, url := range urls { wg.Add(1 ) go func (url string ) { defer wg.Done() http.Get(url) }(url) } wg.Wait() }