文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Go单例模式与Once源码实现

2022-12-08 20:57

关注

单例实现

type singleton struct{}

var (
	instance    *singleton
	initialized uint32
	mu          sync.Mutex
)

func Instance() *singleton {
	if atomic.LoadUint32(&initialized) == 1 {
		return instance
	}

	mu.Lock()
	defer mu.Unlock()

	if instance == nil {
		defer atomic.StoreUint32(&initialized, 1)
		instance = &singleton{}
	}
	return instance
}

其中通用的代码提取出来,就成了标准库中sync.Once的实现:

type Once struct {
	done uint32
	m    sync.Mutex
}

func (o *Once) Do(f func()) {
	if atomic.LoadUint32(&o.done) == 0 {

		o.m.Lock()
		defer o.m.Unlock()

		if o.done == 0 {
			defer atomic.StoreUint32(&o.done, 1)
			f()
		}
	}
}

于是,使用sync.Once重新实现单例模式

var (
	instance2 *singleton
	once sync.Once
)

func Instance2() *singleton {
	once.Do(func() {
		instance2 = &singleton{}
	})
	return instance2
}

sync.Once源码分析

1. lock并不会同步值

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

lock可以通过串行化,使得两个协程的操作存在happen-before关系,从而是的操作可见

happen-before原则定义如下:

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

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

2. Do执行一次

当第一次执行完Do之后,done设置成1,后面执行Do会直接跳过

3. Once执行Do后不准copy

A Once must not be copied after first use.

sync.Once执行完Dodone已经设置成1了,copy出来的once执行Do会直接跳过

4. Do并发时阻塞

当两个或者多个协程同时调用Do时,先调用的协程执行,后面的协程会阻塞;

解释:以单例使用once的实现说明,两个协程同时调用Instance2(),先调用的协程执行创建并拿到返回值,后调用的阻塞,

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

意义:这样的好处是防止后调用的协程拿到的是nil

源码说明:上面第二段代码13行使用defer,要等f()结束才会把done设置成1;其他协程并发调用Do时,done==0

​ 然后请求m.Lock()形成阻塞

5. Do递归死锁

如果Do中的方法调用当前once的Do会造成死锁,原因参考上面一点(sync.Mutex.Lock()时不可重入锁)

参考

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯