当前位置: 首页 > news >正文

范例网站怎么做人力资源培训

范例网站怎么做,人力资源培训,特价手机网站建设,b2b网站收费原文地址:http://marcio.io/2015/07/singleton-pattern-in-go/   最近几年go语言的增长速度非常惊人,吸引着各界人士切换到Go语言。最近有很多关于使用Ruby语言的公司切换到Go、体验Go语言、和Go的并行和并发解决问题的文章。过去10年里,Ruby on Rails已经让众多的…

  原文地址:http://marcio.io/2015/07/singleton-pattern-in-go/  

最近几年go语言的增长速度非常惊人,吸引着各界人士切换到Go语言。最近有很多关于使用Ruby语言的公司切换到Go、体验Go语言、和Go的并行和并发解决问题的文章。
过去10年里,Ruby on Rails已经让众多的开发者和初创公司快速开发出强大的系统,大多数时候不需要担心他的内部是如何工作的,或者担心线程安全和并发。RoR程序很少创建线程和并行的运行一些东西。整个托管的基础建设和框架栈使用不同的方法,通过多个进程来进行并行。最近几年,像Puma这样的多线程机架式服务器开始流行,但是即使是这样,刚开始也带来了很多关于使用第三方gems和其他没有被设计为线程安全的代码的问题。
现在有很多开发者开始使用Go语言。我们需要仔细研究我们的代码,并观察代码的行为,需要以线程安全的方式代码设代码。

常识性错误

   最近,我在很多Github库里看到这种类型的错误,单例模式的实现没有考虑线程安全,下面是常识性错误的代码

  

package singletontype singleton struct {
}var instance *singletonfunc GetInstance() *singleton {if instance == nil {instance = &singleton{}   // <---非线程安全的
    }return instance
}

  

上面的示例中,多个go routines 会进行第一次检查并且都会创建 singleton类型的实例并且互相覆盖。不能保证哪一个实例会被返回,在这个实例上更进一步的操作可能和开发者所期望的不一至。
这样是有问题的,因为如果对这个单例的实例已经在代码中被应用,可能会有潜在的多个这个类型的实例,并用有各自的状态,产生潜在的不同的代码行为。他也可能成为高度时的恶梦,并且很难定位错误,因为在debug时由于运行时暂停减少潜在的非线程安全的执行而不会真正出现错误,很容易隐藏开发者的问题。

激进的锁

  我也看到一些使用糟糕的方法来解决线程安全的问题。事实上他解决了多线程的问题,但是创造了其他潜在的更严重的问题,他通过对整个方法执行锁定来引入线程竞争

var mu Sync.Mutexfunc GetInstance() *singleton {mu.Lock()                    // <--- 如果实例已经被创建就没有必要锁写
    defer mu.Unlock()if instance == nil {instance = &singleton{}}return instance
}
上面的代码,我们可以看到,通过引入Sync.Mutex来解决线程安全的问题,并且在创建单例实例前获取锁。问题在于当我们不需要的时候例如,实例已经被创建的时候,只需要返回缓存的单例实例,但是呢也会执行锁操作。在高并发代码基础上,这会产生瓶颈,因为在同一时间只有一个go routine可以得到单例的实例。
所以这不是最好的方法,我们找找其他的解决方案。

 Check-Lock-Check 模式

   在c++和其他语言,用于保证最小锁定并且保证线程安全的最好、最安全的方式是当需要锁定时使用众所周知的Check-Lock-Check模式。下面的伪代码说明了这个模式的大概样子

if check() {lock() {if check() {// perform your lock-safe code here
        }}
}

 

这个模式背后的想法是想一开始就检查。用于减少任何激进的锁定。因为一个IF语句比锁定便宜的多。第二我们想等待并获取排他锁所以的块内同一时间只能有一个执行,但是在第一次检察和和排他锁获取之间可能会有其他线程想要获取锁,因此我们需要在块内再次的检查以避免单例实例被其他实例替换。
多年来,和我一起工作人的熟知这一点,在代码审过程中,这个模式和线程安全思想方面,我对团队非常严厉。
如果我们应用这个模式到我的GetInstance()方法,我们需要做的如下 :
func GetInstance() *singleton {if instance == nil {     // <-- 不够完善. 他并不是完全的原子性
        mu.Lock()defer mu.Unlock()if instance == nil {instance = &singleton{}}}return instance
}
这是一个挺好的方法,但是并不完美。因为编译器优化,但是没有实例保存的状态的原子性检查。全面的技术考虑,这并不是安美的。但是已经比之前的方法好多了。   
但是使用 sync/atomic 包,我们可以原子性的加载和设置标识指示是否已经初始化了我们的实例。
import "sync"
import "sync/atomic"var initialized uint32
...func GetInstance() *singleton {if atomic.LoadUInt32(&initialized) == 1 {return instance}mu.Lock()defer mu.Unlock()if initialized == 0 {instance = &singleton{}atomic.StoreUint32(&initialized, 1)}return instance
}

 

   但是.....我相信我们可以通过查看Go语言和标准库的源码看一下go routines 同步的实现方式来做的更好

 Go惯用的单例方法

   我们想要使用Go的惯用手法来实现这个单例模式。所以我们需要看一下打包好的sync标准库。我们找到了 Once 类型。这个对象可以精确的只执行一次操作,下面就是Go标准库的代码

// Once is an object that will perform exactly one action.
type Once struct {m    Mutexdone uint32
}// Do calls the function f if and only if Do is being called for the
// first time for this instance of Once. In other words, given
//     var once Once
// if once.Do(f) is called multiple times, only the first call will invoke f,
// even if f has a different value in each invocation.  A new instance of
// Once is required for each function to execute.
//
// Do is intended for initialization that must be run exactly once.  Since f
// is niladic, it may be necessary to use a function literal to capture the
// arguments to a function to be invoked by Do:
//     config.once.Do(func() { config.init(filename) })
//
// Because no call to Do returns until the one call to f returns, if f causes
// Do to be called, it will deadlock.
//
// If f panics, Do considers it to have returned; future calls of Do return
// without calling f.
//
func (o *Once) Do(f func()) {if atomic.LoadUint32(&o.done) == 1 { // <-- Checkreturn}// Slow-path.o.m.Lock()                           // <-- Lock
    defer o.m.Unlock()if o.done == 0 {                     // <-- Checkdefer atomic.StoreUint32(&o.done, 1)f()}
}

 

  这意味着我们可以运用非常棒的 Go sync包来调用一个只执行一次的方法。因此,我们可以向下面这样调用 once.Do() 方法

once.Do(func() {// 执行安全的初始化操作
})

  下面你可以看到使用sync.Once类型实现的单例实现的完整代码,用于同步访问GetInstance() 并保证我们的类型初始化只执行一次。

package singletonimport ("sync"
)type singleton struct {
}var instance *singleton
var once sync.Oncefunc GetInstance() *singleton {once.Do(func() {instance = &singleton{}})return instance
}

 

因此,使用sync.Once包是一个完美的安全的实现方式,这种方式有点像Object-C和Swift(Cocoa)的实现dispatch_once 方法用于执行类似的初始化操作。

     总结

当涉及到并行和并发代码时,需要详细检查你的代码。始终让你的团队成员进行代码审查,因此对于这样的事情才能更容易的监督。
所有的切换到Go语言的新开发者,需要明确的理解线程安全的原理才能更好的改善你的代码。即使Go语言本身通过做了很多努力允许你使用很少的并发知识来设计并发代码。仍有一些语言无法帮你处理的一些情况,你依然需要在开发代码时应用最佳的实践方法

 

http://www.lbrq.cn/news/2525617.html

相关文章:

  • 网站的建设任务百度旗下的所有产品
  • dreamweaver怎么读南昌seo技术外包
  • 宜宾县企业项目建设影响环境登记表网站肇庆seo
  • 网站建设 开源百度站长工具平台登录
  • 青岛市规划建设局网站网站排名首页前三位
  • 网站后台怎么修改淄博网站制作
  • 济宁网站建设平台百度推广官方
  • seo是搜索引擎优化吗抖音seo优化怎么做
  • 外贸免费网站建设买友情链接有用吗
  • 征婚网站怎么做网站推广策划书模板
  • 青岛互联网设计公司一个具体网站的seo优化方案
  • 公司网站制作需要什么长沙网络营销公司排名
  • 甘肃做高端网站排名网站
  • 南京营销型网站制作网站建设工作总结
  • 汕头百度公司南宁seo推广优化
  • 去设计公司还是去企业焦作网站seo
  • 网站导航做多大网站关键词优化工具
  • 长春 万网 网站建设关键词seo排名优化推荐
  • 维护网站计划书什么软件可以搜索关键词精准
  • 长沙百度做网站多少钱河南关键词优化搜索
  • 青岛公司网站佛山网络推广哪里好
  • 网站后台怎样登陆win10优化工具下载
  • 优化学校网站建设方案体验营销策划方案
  • 国内室内设计seo推广学院
  • 北京电商网站建设比较成功的网络营销案例
  • 做网站需要后端吗百度推广管理
  • wordpress 显示指定分类文章列表长沙谷歌优化
  • php和java哪个做网站浩现在广告行业好做吗
  • 什么建设网站百度网站优化
  • 网站制作中企动力公司软文案例短篇
  • Redis学习------缓存雪崩
  • C++类中动态内存分配注意手册
  • 青少年软件编程图形化Scratch等级考试试卷(四级)2025年6月
  • vue相关的拖拉拽官网
  • Arduino与STM32:初学者该如何选择?
  • mybatis-plus实体类主键生成策略