sync包里的对象,大多是不能复制的 -------------------------------------------------------------------------------- 锁 sync.Mutex的Lock()方法,是不能重入的 var mu sync.Mutex // 零值表示未被锁定的互斥量 mu.Lock() defer mu.Unlock() // 对未锁定的锁进行Unlock,会导致panic var mu sync.RWMutex // RWMutex的写锁,是Lock()和Unlock(),没有WLock() mu.RLock() defer mu.RUnlock() -------------------------------------------------------------------------------- 条件变量 cond := sync.NewCond(new(sync.Mutex)) // 条件变量关联某个锁 condition := 0 go func() { // 消费者 for { cond.L.Lock() // 消费者开始消费时,锁住 for condition == 0 { cond.Wait() } // 如果没有可消费的值,则等待 condition-- // 消费 fmt.Printf("Consumer: %d\n", condition) cond.Signal() // 唤醒一个生产者 cond.L.Unlock() // 解锁 } }() for { // 生产者 cond.L.Lock() // 生产者开始生产 for condition == 100 { cond.Wait() } // 当生产太多时,等待消费者消费 condition++ // 生产 fmt.Printf("Producer: %d\n", condition) cond.Signal() // 通知消费者可以开始消费了 cond.L.Unlock() // 解锁 } -------------------------------------------------------------------------------- 原子操作 每种原子操作支持的类型都有限 加减 Add newi32 := atomic.AddInt32(&i32, 3) // 加3,i32也会被修改 atomic.AddUint32(&ui32, ^uint32(-N-1)) // 对uint32类型加N,N是负常数, 比较并交换 CAS for { a := b if atomic.CompareAndSwapInt32(&b, a, a+3) { break } } 载入 Load 并发读变量时,可能读到错误的值,例如32位机器上对int64进行写入,可能读到改了一半的数据 a := atomic.LoadInt32(&b) // cpu不会执行其他针对此值的读写操作 存储 Store开头的一组函数,cpu不会执行其他针对此值的读写操作 交换 Swap开头的一组函数,设置新值,返回旧值 atomic.Value是结构体,有两个方法:Load和Store,可以原子地读写任意类型的值, Load不接受参数,返回一个interface{}类型的结果,对没有Store过的atomic.Value执行Load,返回nil Store接受一个interface{}类型的参数,没有返回值,不能传nil,若之前Store过值,那么后来Store的值必须与之前Store的值具有相同的类型 只执行一次 var once sync.Once once.Do( func () { ... } ) sync.WaitGroup是结构体类型,用字节数组代表计数,其中4字节表示给定计数,另外4字节表示等待计数 var wg sync.WaitGroup // wg在wait()返回之后可以重用 wg.Add(3) // 增加给定计数3,可以传负数,但给定计数不能小于0 wg.Done() // 给定计数减1,同样不能减成负数,否则panic 当给定计数减为0时,会唤醒所有阻塞的goroutine,并将等待计数置为0 wg.wait() // 如果给定计数为0,则立即返回,否则阻塞,并把等待计数加1 // 可以有多个wait()调用,当计数为0时,多个wait()都将返回 sync.Pool New字段 可被赋值为一个函数 func() interface{},该函数用于在Pool为空时生成一个对象, 生成的对象不会被放进Pool里,而是直接返回给调用Get方法的调用方 Get方法 用于从Pool里获取任意的一个interface{}类型的值,并将其从Pool里删除。 优先从本地P对应的私有池和共享池获取对象,其次从其他P的共享池偷一个对象 如果Pool为空,就调用New字段保存的函数来得到一个对象, 如果New没有被赋值为函数就返回nil Put方法 用于把一个interface{}类型的值放入Pool中 垃圾回收时,Pool里的全部对象都会被移除 p := sync.Pool{ New : func() interface{} { return 0 }, } a := p.Get().(int) p.put(2) --------------------------------------------------------------------------------
golang标准库 sync
猜你喜欢
转载自www.cnblogs.com/ts65214/p/12976197.html
今日推荐
周排行