------------------------------------------------------------临时对象池Pool 用于存储临时对象,它将使用完毕的对象存入对象池中,在需要的时候取出来重复使用,目的是为了避免重复创建相同的对象造成 GC 负担过重。其中存放的临时对象随时可能被 GC 回收掉(如果该对象不再被其它变量引用)。从 Pool 中取出对象时,如果 Pool 中没有对象,将返回 nil,但是如果给 Pool.New 字段指定了一个函数的话,Pool 将使用该函数创建一个新对象返回。Pool 可以安全的在多个例程中并行使用,但 Pool 并不适用于所有空闲对象,Pool 应该用来管理并发的例程共享的临时对象,而不应该管理短寿命对象中的临时对象,因为这种情况下内存不能很好的分配,这些短寿命对象应该自己实现空闲列表。Pool 在开始使用之后,不能再被复制。------------------------------type Pool struct {// 创建临时对象的函数New func() interface{}
}// 向临时对象池中存入对象
func (p *Pool) Put(x interface{})// 从临时对象池中取出对象
func (p *Pool) Get() interface{}------------------------------------------------------------单次执行Once 的作用是多次调用但只执行一次,Once 只有一个方法,Once.Do(),向 Do 传入一个函数,这个函数在第一次执行 Once.Do() 的时候会被调用,以后再执行 Once.Do() 将没有任何动作,即使传入了其它的函数,也不会被执行,如果要执行其它函数,需要重新创建一个 Once 对象。Once 可以安全的在多个例程中并行使用。------------------------------// 多次调用仅执行一次指定的函数 f
func (o *Once) Do(f func())------------------------------// 示例:Once
func main() {var once sync.OnceonceBody := func() {fmt.Println("Only once")}done := make(chan bool)for i := 0; i < 10; i++ {go func() {once.Do(onceBody) // 多次调用只执行一次done <- true}()}for i := 0; i < 10; i++ {<-done}
}// 输出结果:
// Only once------------------------------------------------------------互斥锁互斥锁用来保证在任一时刻,只能有一个例程访问某对象。Mutex 的初始值为解锁状态。Mutex 通常作为其它结构体的匿名字段使用,使该结构体具有 Lock 和 Unlock 方法。Mutex 可以安全的在多个例程中并行使用。------------------------------// Locker 接口包装了基本的 Lock 和 UnLock 方法,用于加锁和解锁。
type Locker interface {Lock()Unlock()
}// Lock 用于锁住 m,如果 m 已经被加锁,则 Lock 将被阻塞,直到 m 被解锁。
func (m *Mutex) Lock()// Unlock 用于解锁 m,如果 m 未加锁,则该操作会引发 panic。
func (m *Mutex) Unlock()------------------------------// 示例:互斥锁
type SafeInt struct {sync.MutexNum int
}func main() {count := SafeInt{}done := make(chan bool)for i := 0; i < 10; i++ {go func(i int) {count.Lock() // 加锁,防止其它例程修改 countcount.Num += ifmt.Print(count.Num, " ")count.Unlock() // 修改完毕,解锁done <- true}(i)}for i := 0; i < 10; i++ {<-done}
}// 输出结果(不固定):
// 2 11 14 18 23 29 36 44 45 45------------------------------------------------------------读写互斥锁RWMutex 比 Mutex 多了一个“读锁定”和“读解锁”,可以让多个例程同时读取某对象。RWMutex 的初始值为解锁状态。RWMutex 通常作为其它结构体的匿名字段使用。Mutex 可以安全的在多个例程中并行使用。------------------------------// Lock 将 rw 设置为写锁定状态,禁止其他例程读取或写入。
func (rw *RWMutex) Lock()// Unlock 解除 rw 的写锁定状态,如果 rw 未被写锁定,则该操作会引发 panic。
func (rw *RWMutex) Unlock()// RLock 将 rw 设置为读锁定状态,禁止其他例程写入,但可以读取。
func (rw *RWMutex) RLock()// Runlock 解除 rw 的读锁定状态,如果 rw 未被读锁顶,则该操作会引发 panic。
func (rw *RWMutex) RUnlock()// RLocker 返回一个互斥锁,将 rw.RLock 和 rw.RUnlock 封装成了一个 Locker 接口。
func (rw *RWMutex) RLocker() Locker------------------------------------------------------------组等待WaitGroup 用于等待一组例程的结束。主例程在创建每个子例程的时候先调用 Add 增加等待计数,每个子例程在结束时调用 Done 减少例程计数。之后,主例程通过 Wait 方法开始等待,直到计数器归零才继续执行。------------------------------// 计数器增加 delta,delta 可以是负数。
func (wg *WaitGroup) Add(delta int)// 计数器减少 1
func (wg *WaitGroup) Done()// 等待直到计数器归零。如果计数器小于 0,则该操作会引发 panic。
func (wg *WaitGroup) Wait()------------------------------// 示例:组等待
func main() {wg := sync.WaitGroup{}wg.Add(10)for i := 0; i < 10; i++ {go func(i int) {defer wg.Done()fmt.Print(i, " ")}(i)}wg.Wait()
}// 输出结果(不固定):
// 9 3 4 5 6 7 8 0 1 2------------------------------------------------------------条件等待条件等待通过 Wait 让例程等待,通过 Signal 让一个等待的例程继续,通过 Broadcast 让所有等待的例程继续。在 Wait 之前应当手动为 c.L 上锁,Wait 结束后手动解锁。为避免虚假唤醒,需要将 Wait 放到一个条件判断循环中。官方要求的写法如下:c.L.Lock()
for !condition() {c.Wait()
}
// 执行条件满足之后的动作...
c.L.Unlock()Cond 在开始使用之后,不能再被复制。------------------------------type Cond struct {L Locker // 在“检查条件”或“更改条件”时 L 应该锁定。
} // 创建一个条件等待
func NewCond(l Locker) *Cond// Broadcast 唤醒所有等待的 Wait,建议在“更改条件”时锁定 c.L,更改完毕再解锁。
func (c *Cond) Broadcast()// Signal 唤醒一个等待的 Wait,建议在“更改条件”时锁定 c.L,更改完毕再解锁。
func (c *Cond) Signal()// Wait 会解锁 c.L 并进入等待状态,在被唤醒时,会重新锁定 c.L
func (c *Cond) Wait()------------------------------// 示例:条件等待
func main() {condition := false // 条件不满足var mu sync.Mutexcond := sync.NewCond(&mu)// 让例程去创造条件go func() {mu.Lock()condition = true // 更改条件cond.Signal()    // 发送通知:条件已经满足mu.Unlock()}()mu.Lock()// 检查条件是否满足,避免虚假通知,同时避免 Signal 提前于 Wait 执行。for !condition {// 等待条件满足的通知,如果收到虚假通知,则循环继续等待。cond.Wait() // 等待时 mu 处于解锁状态,唤醒时重新锁定。}fmt.Println("条件满足,开始后续动作...")mu.Unlock()
}// 输出结果:
// 条件满足,开始后续动作...------------------------------------------------------------

Golang学习 - sync 包相关推荐

  1. Golang学习 - bufio 包

    ------------------------------------------------------------// bufio 包实现了带缓存的 I/O 操作---------------- ...

  2. golang的sync包例子

    package mainimport ("fmt""sync" )var wg sync.WaitGroupfunc asyncTestFunc() {for ...

  3. Golang学习 - unicode 包

    ------------------------------------------------------------const (MaxRune = '\U0010FFFF' // Unicode ...

  4. Golang学习(10)——bufio包

    Golang学习 - bufio 包 ------------------------------------------------------------ // bufio 包实现了带缓存的 I/ ...

  5. Golang学习(12)——regex包

    Golang学习 - regexp 包 ------------------------ // 函数 // 判断在 b(s.r)中能否找到 pattern 所匹配的字符串 func Match(pat ...

  6. 从项目的一个 panic 说起:Go 中 Sync 包的分析应用

    项目开发中遇到一个错误 "fatal error: concurrent map read and map write". 有过一两年 Golang 开发经验的同学应该都不陌生,这 ...

  7. golang中的包管理工具——govendor和godep简单学习

    为什么用vendor目录 依赖问题 我们知道,一个工程稍大一点,通常会依赖各种各样的包.而Go使用统一的GOPATH管理依赖包,且每个包仅保留一个版本.而不同的依赖包由各自的版本工具独立管理,所以当所 ...

  8. golang学习之negroni/gizp源码分析

    在 Go 语言里,Negroni 是一个很地道的 Web 中间件,它是一个具备微型.非嵌入式.鼓励使用原生 net/http 库特征的中间件.利用它地Use功能,我们可以很简单地自定义中间件并使用.其 ...

  9. golang学习笔记(进阶篇)

    四.Golang进阶部分(并发) 并发编程在当前软件领域是一个非常重要的概念,随着CPU等硬件的发展,我们无一例外的想让我们的程序运行的快一点.再快一点.Go语言在语言层面天生支持并发,充分利用现代C ...

最新文章

  1. PyTorch深度学习
  2. 2049 : 压死骆驼的最后一根稻草 (规律)
  3. 在类中用class时数据是共有还是私有_jvm学习笔记之class文件的加载、初始化
  4. 如何限制对象只能建立在堆上或者栈上
  5. Python与机器视觉(一)安装与环境
  6. 异步生成器_使用生成器实现异步并等待
  7. 多行文本溢出显示省略号
  8. 多个Tomcat同时运行环境配置 - imsoft.cnblogs
  9. Windows基础知识整理
  10. 调速水泵控制c语言实验程序,液压控制实验报告
  11. 北京/上海内推 | 微软亚洲研究院系统与网络组招聘全职实习生
  12. [Swift]LeetCode882. 细分图中的可到达结点 | Reachable Nodes In Subdivided Graph
  13. 移植ffmpeg到android_1
  14. 懂得,是生命中最美的缘
  15. 金融时间序列分析:8. MA模型实例(Python)
  16. Typora软件图片丢失问题
  17. 远程实时监控搭建_远程学习的烦恼正在实时展开
  18. 计算机软件著作权申请表中开发运行环境、技术特点等项目的编写指南
  19. SAP BASIS ADM100 中文版 Unit 5(4)
  20. 图像视频的常用概念HDR/WDR等

热门文章

  1. micropython lcd12864_Esp8266+ssd1306液晶屏+microPython(2020-09-25)
  2. C++自学17:goto
  3. SpringMvc-PropertyEditor接口和@InitBinder注解
  4. Bootstrap-datetimepicker控件使用
  5. linux 托盘两个输入法图标,linux mint12安装ibus之后,语言栏不跟随光标和系统托盘输入法图标不能显示问题解决...
  6. cinder与ceph的区别_配置cinder-volume服务使用ceph作为后端存储
  7. 惩罚函数外点matlab,禁忌搜索算法求解带时间窗的车辆路径问题(惩罚函数版 附MATLAB代码)...
  8. yolov2训练_YOLOv2 : YOLO9000:Better,Faster,Stronger解读
  9. jQuery-点击按钮页面滚动到顶部,底部,指定位置
  10. Strut2页面传参跳转 --Struts2