前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang标准库-sync包使用和应用场景

Golang标准库-sync包使用和应用场景

原创
作者头像
小许code
发布2023-02-22 09:34:37
5890
发布2023-02-22 09:34:37
举报
文章被收录于专栏:小许code

sync包

大家好,我是小许,标准库中的sync包在我们的日常开发中用的颇为广泛,那么大家对sync包的用法知道多少呢,这篇文章就大致讲一下sync包和它的使用

Package sync provides basic synchronization primitives such as mutual exclusion locks. Other than the Once and WaitGroup types, most are intended for use by low-level library routines. Higher-level synchronization is better done via channels and communication. Values containing the types defined in this package should not be copied.

这句话大意就是说:sync包提供了基本的同步基元,如互斥锁。除了Once和WaitGroup类型,大部分都是适用于低水平程序线程,高水平的同步使用channel通信更好一些

包中定义了以下类型: Locker, Once, Mutex, RWMutex, WaitGroup, Pool。接下来我们逐个讲每种类型的使用,所有这些在Go sdk中的src/runtime/sync包,可逐个查看,特别是结合test一起

1.Locker

Locker接口,包含Lock()和Unlock()两个方法,用于代表一个能被加锁和解锁的对象.

Locker接口

1.1 Lock()

Lock方法锁住Mutex,如果Mutex已经加锁,则阻塞直到m解锁

1.2 UnLock()

Unlock方法解锁m,如果解锁一个未加锁的mutex会导致运行时错误、锁定m与特定的groutine无关。允许不同的groutine进行加锁、解锁

2.Once

Once是只执行一次动作的对象,使用后不得复制

Once结构

Once只有一个Do方法

代码语言:javascript
复制
var once Once
func (o *Once) Do(f func())

Do方法当且仅当第一次被调用时才执行函数f。once.Do(f)被多次调用,只有第一次调用会执行f,即使f每次调用Do 提供的f值不同。需要给每个要执行仅一次的函数都建立一个Once类型的实例

3.Mutex

Mutex是一个互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。实现了Locker()接口的UnLock()和Locker()方法,同一时刻一段代码只能被一个线程运行

Mutex在大量并发的情况下,会造成锁等待,对性能的影响比较大

Mutex结构

4.RWMutex

Mutex是一个读写互斥锁,该锁可以被同时多个读取者持有或唯一个写入者持有

有以下方法可使用

5.WaitGroup

WaitGroup 对象内部有一个计数器,最初从0开始,它有三个方法:Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 把计数器设置为n ,Done() 每次把计数器-1 ,wait() 会阻塞代码的运行,直到计数器的值减为0.

代码语言:javascript
复制
//将WaitGroup的计数器增加delta,delta可以为负值。如果WaitGroup的计数器变为0则所有阻塞在Wait()的gorouting将会被释放,如果计数器变为负值则会panic
//Add应该在创建gourouting之前执行,如果重用WaitGroup,必须要等到之前所有Wait都返回后再重新Add。
func (wg *WaitGroup) Add(delta int)

//将WaitGroup计数器减1
func (wg *WaitGroup) Done()

//阻塞等待直至WaitGroup计数器变为0
func (wg *WaitGroup) Wait()

使用示例

代码语言:javascript
复制
func main() {
    wg := sync.WaitGroup{}
    wg.Add(5)
    for i := 0; i < 5; i++ {
        go func(i int) {
            fmt.Println(i)
            wg.Done()
        }(i)
    }
    //阻塞直到所有的groutine都执行完
    wg.Wait()
}

6.Pool

Pool是一个可以分别存取的临时对象的集合,可以被看作是一个存放可重用对象的值的容器、过减少GC来提升性能,是Goroutine并发安全的。有两个方法 Get()、Set()

代码语言:javascript
复制
//Get方法没有取得item:如p.New非nil,Get返回调用p.New的结果;否则返回nil
func (p *Pool) Get() interface{}

//将对象放入对象池中
func (p *Pool) Put(x interface{})

//New初始化Pool实例
bufferpool := &sync.Pool {
    New: func() interface {} {
        println("Create pool instance")
        return struct{}{}
    }
}

其实在开发使用中我们间接也是使用到了sync.Pool,比如标准库中的fmt、还有gin、iris框架中的Context

6.1 fmt中sync.Pool

newPrinter就是调用的sync.Pool.Get(),拿到pp指针.首先是做了一些format操作。然后调用free()方法,将使用过得pp放回到ppFree中。归还之前将p的部分字段重置,以保证下次调用的是原始pp

代码语言:javascript
复制
//fmt.Printf

func Printf(format string, a ...interface{}) (n int, err error) {
    return Fprintf(os.Stdout, format, a...)
}

func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
    p := newPrinter()
      ...
      //使用完后释放,将pp归还给了sync.pool
    p.free()
    return
}

//返回一个pp结构体指针
func newPrinter() *pp {
    p := ppFree.Get().(*pp)
    p.panicking = false
    p.erroring = false
    p.wrapErrs = false
    p.fmt.init(&p.buf)
    return p
}


var ppFree = sync.Pool{
    New: func() interface{} { return new(pp) },
}

//结构体pp
type pp struct {
  ...
}

6.2 iris框架中的Context中的sync.Pool

iris.New()创建并返回一个空的 iris *Application实例。New()函数中的context.New(),传入一个func,返回一个context.Pool给到 Application的ContextPool。可以看到传入的func实际是给到了sync.Pool.New。app.ContextPool就是存储上下文变量Context的管理池。

Acquire()获取context, Release()释放对象

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • sync包
  • 1.Locker
    • 1.1 Lock()
    • 2.Once
    • 3.Mutex
    • 4.RWMutex
    • 5.WaitGroup
    • 6.Pool
      • 6.1 fmt中sync.Pool
        • 6.2 iris框架中的Context中的sync.Pool
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档