Go单例模式与Once源码实现

单例实现

sync.Once
sync.Once

sync.Once源码分析

1. lock并不会同步值

在lock和unlock之间修改值,并不会保证对其他协程是可见的,除非使用相同的Mutex加锁,想要同步值必须使用atomic;

happen-before
happen-before

如果一个操作happens-before(之前发生)另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。

两个操作之间存在happens-before关系,并不意味着一定要按照happens-before原则制定的顺序来执行。如果重排序之后的执行结果与按照happens-before关系来执行的结果一致,那么这种重排序并不非法。

2. Do执行一次

DodoneDo

3. Once执行Do后不准copy

A Once must not be copied after first use.

sync.OnceDodoneDo

4. Do并发时阻塞

Do
Instance2()

​ 等到先调用的完成后再拿到返回值;

nil
deferf()doneDodone==0
m.Lock()

5. Do递归死锁

DoDosync.Mutex.Lock()

参考

  • 《Go语言高级编程》
  • Go1.16源码