典型并发任务

  • 只运行一次

懒汉式,线程安全

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之前 

posted @ 2020-06-10 16:03  LinBupt  阅读(149)  评论(0编辑  收藏  举报