典型并发任务
- 只运行一次
懒汉式,线程安全
var once sync.Once var obj *SingletonObj func GetSingletonObj() *SingletonObj { once.Do(func() { fmt.Println("Create Singleton obj.") obj = &SingletonObj{} }) return obj }
package once_test import "sync" type Singleton struct{ } var singleInstance *Singleton var once sync.Once func GetSingletonObj() *Singleton { once.Do(func() { fmt.Println("Create Obj") singleInstance = new(Singleton) }) return singleInstance } func TestGetSingletonObj(t *testing.T) { var wg sync.WaitGroup for i:=0; I<10; I++{ wg.Add(1) go func() { obj := GetSingletonObj() fmt.Printf("%x\n", unsafe.Pointer(obj)) wg.Done() }() } wg.Wait() }
- 仅需任意任务完成
CSP
func runTask(id int) string { time.Sleep(10 * time.Millisecond) return fmt.Sprintf("The result is from %d", id) } func FirstResponse() string { numOfRunner := 10 ch := make(chan string, numOfRunner) for i := 0; i < numOfRunner; i++{ go func(I int) { ret := runTask(i) ch <- ret }(i) } return <-ch //channel的阻塞机制 } func TestFirstResponse(t *testing.T) { t.Log("Before:",runtime.NumGoroutine()) t.Log(FirstRespoonse()) t.Log("Befor:",runtime.NumGoroutine()) }
- 所有任务完成
sync.wg
CSP
func runTask(id int) string { time.Sleep(10 * time.Millisecond) return fmt.Sprintf("The result is from %d", id) } func AllResponse() string { numOfRunner := 10 ch := make(chan string, numOfRunner) for i := 0; i < numOfRunner; i++{ go func(I int) { ret := runTask(i) ch <- ret }(i) } finalRet := "" for j:=0;j<numOfRunner;j++{ finalRet += <-ch + "\n" } return finalRet } func TestAllResponse(t *testing.T) { t.Log("Before:",runtime.NumGoroutine()) t.Log(AllRespoonse()) t.Log("Befor:",runtime.NumGoroutine()) }
- 对象池
数据库连接、网络连接
使用buffered channel实现对象池
- sync.pool对象缓存
sync.Pool对象获取
尝试从私有对象获取(私有对象:协程安全;共享池:协程不安全的)
私有对象不存在,尝试从当前Processor的共享池获取
如果当前Processor共享池也是空的,那么就尝试去其他Processor的共享池获取
如果所有子池都是空的,最后就用用户指定的New函数产生一个新的对象返回
sync.Pool对象的放回
如果私有对象不存在则保存为私有对象
如果私有对象存在,放入当前Processor子池的共享池中
使用sync.Pool
pool := &sync.Pool{ New: func() interface{} { return 0 }, } array := pool.Get().(int) ... pool.Put(10)
sync.Pool对象的生命周期
GC会清除sync.pool缓存的对象;对象的缓存有效期为下一次GC之前