golang下sync包整理

sync.Mutex

1
2
3
4
5
6
7
8
9
10
11
12
type Locker interface {
Lock()
Unlock()
}
互斥锁 Mutex
func (m *Mutex) Lock()
func (m *Mutex) Unlock()
读写锁 RWMutex
func (rw *RWMutex) Lock()
func (rw *RWMutex) Unlock()
func (rw *RWMutex) RLock()
func (rw *RWMutex) RUnlock()

同时只能有一个 goroutine 能够获得写锁定。
同时可以有任意多个 gorouinte 获得读锁定。
同时只能存在写锁定或读锁定(读和写互斥)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main(){
var a = 0
var lock sync.Mutex
//var rwlock sync.RWMutex
for i:=0; i<50;i++{
go func(idx int) {
lock.Lock()
defer lock.Unlock()
a+=1
fmt.Printf("goroutine %d, a=%d\n", idx, a)
}(i)
}
time.Sleep(time.Second)
}

sync.Once

1
2
3
4
5
type Once struct {
// 非暴露字段
}

func (o *Once) Do(f func())

使用前先定义 Once 类型变量:var once Once
使用的时候向 Once 类型变量传入函数:once.Do(func() { init() })

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
import (
"fmt"
"sync"
)

func main(){
testOnce()
}
func testOnce(){
var once sync.Once
testOnceFunction := func(){
fmt.Println("Only once")
}
done := make(chan bool)
a:=0
var lock sync.Mutex
for i:=0;i<10;i++{
go func(){
lock.Lock()
defer lock.Unlock()
once.Do(testOnceFunction)
fmt.Println("a=",a)
a++
done <-true
}()
}
for j:=0;j<10;j++{
<-done
}
}

sync.Pool

1
2
3
4
type Pool
func (p *Pool) Get() interface{}
func (p *Pool) Put(x interface{})
New func() interface{}

这个类设计的目的是用来保存和复用临时对象,以减少内存分配,降低CG压力。
Get返回Pool中的任意一个对象。
如果Pool为空,则调用New返回一个新创建的对象。
如果没有设置New,则返回nil。
还有一个重要的特性是,放进Pool中的对象,会在说不准什么时候被回收掉。
所以如果事先Put进去100个对象,下次Get的时候发现Pool是空也是有可能的。
不过这个特性的一个好处就在于不用担心Pool会一直增长,因为Go已经帮你在Pool中做了回收机制。
这个清理过程是在每次垃圾回收之前做的。垃圾回收是固定两分钟触发一次。
而且每次清理会将Pool中的所有对象都清理掉!

1
2
3
4
5
6
7
8
9
10
11
12
func main(){
// 建立对象
var pipe = &sync.Pool{New:func()interface{}{return "Hello,BeiJing"}}
// 准备放入的字符串
val := "Hello,World!"
// 放入
pipe.Put(val)
// 取出
log.Println(pipe.Get())
// 再取就没有了,会自动调用NEW
log.Println(pipe.Get())
}