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

网站后台 批量上传app排名优化公司

网站后台 批量上传,app排名优化公司,日本做h动漫电影网站,广东品牌网站建设报价在使用Golang做后端开发的工程中,我们通常需要声明一些一些配置类或服务单例等在业务逻辑层面较为底层的实例。为了节省内存或是冷启动开销,我们通常采用lazy-load懒加载的方式去初始化这些实例。初始化单例这个行为是一个非常经典的并发处理的案例&…

在使用Golang做后端开发的工程中,我们通常需要声明一些一些配置类或服务单例等在业务逻辑层面较为底层的实例。为了节省内存或是冷启动开销,我们通常采用lazy-load懒加载的方式去初始化这些实例。初始化单例这个行为是一个非常经典的并发处理的案例,比如在java当中,我们可能用到建立双重锁+volatile的方式保证初始化逻辑只被访问一次,并且所有线程最终都可以读取到初始化完成的实例产物。这段经典的代码可以按如下的方式编写:

// 参考:https://blog.csdn.net/qq_27489007/article/details/84966680public class Singleton {private volatile static Singleton uniqueSingleton;private Singleton() {}public Singleton getInstance() {if (null == uniqueSingleton) {synchronized (Singleton.class) {if (null == uniqueSingleton) {uniqueSingleton = new Singleton();}}}return uniqueSingleton;}
}

但在Golang里面,实现懒加载的方式可以简单的多,用内置的sync.Once就能满足。假设我们有一个user单例,需要被1000个线程读取并打印,就可以这样子写:

type User struct {Name string `json:"name"`Age  int    `json:"age"`
}var user *User
var userOnce sync.Oncefunc initUser() {user = &User{}cfgStr := `{"name":"foobar","age":18}`if err := json.Unmarshal([]byte(cfgStr), user); err != nil {panic("load user err: " + err.Error())}
}func getUser() *User {userOnce.Do(initUser)return user
}func TestSyncOnce(t *testing.T) {var wg sync.WaitGroupfor i := 1; i < 1000; i++ {wg.Add(1)go func(n int) {defer wg.Done()curUser := getUser()t.Logf("[%d] got user: %+v", n, curUser)}(i)}wg.Wait()
}

这段代码里,首先是通过var userOnce sync.Once声明了一个sync.Once实例,然后在getUser当中,我们声明了userOnce.Do(initUser)这个操作。假设一个goroutine最先到达这个操作,就会上锁并执行initUser,其它goroutine到达之后,得等第一个goroutine执行完initUser之后,才会继续return user。这样,就能一来保证initUser只会执行一次,二来所有goroutine都能够最终读到初始化完成的user单例。

sync.Once的工作机理也很简单,通过一个锁和一个flag就能够实现:

func (o *Once) Do(f func()) {if atomic.LoadUint32(&o.done) == 0 { // 如果是1表示已经完成了,跳过o.doSlow(f)}
}func (o *Once) doSlow(f func()) {o.m.Lock() // 只有1个goroutine能拿到锁,其它的等待defer o.m.Unlock()if o.done == 0 { // 如果还是0表示第一个来的,不是0就表示已经有goroutine做完了defer atomic.StoreUint32(&o.done, 1)f()}
}

最后也需要注意,sync.Once使用上面有一个坑点,不能也不需要像java一样为单例提前做nil判断。比如下面一段代码是有问题的:

func initUser() {user = &User{} // 先给一个zero-value实例cfgStr := `{"name":"foobar","age":18}` // 然后加载json内容,完成初始化if err := json.Unmarshal([]byte(cfgStr), user); err != nil {panic("load user err: " + err.Error())}
}func getUser() *User {if user == nil {userOnce.Do(initUser)}return user
}

由于Golang没有volatile关键字,不能控制单例在内存的可见性,那么多goroutine并发时,就有可能出现这样的执行时序:

  • goroutine-A过了getUseruser == nil判断,进入到了initUser逻辑,走到了cfgStr := XXX一行
  • 此时切换到goroutine-B,因为goroutine-AinitUser已经走过了user = &User{}一行,所以跳过了user == nil判断,直接返回没有完全初始化的user实例,然后一直往下运行,就没切回给goroutine-A

这样的结果,就导致有goroutine拿到未初始化完成的实例往后运行,后面就出问题了。所以实战当中需要留意,用sync.Once时,不能也不需要加这些nil判断,就能满足懒加载单例/配置之类的逻辑。

http://www.hengruixuexiao.com/news/38584.html

相关文章:

  • 打开一个网站搜索页面跳转js百度站长工具怎么查排名
  • 高端品牌网站设计关键词优化公司网站
  • 做JSP网站买什么书小程序源码网
  • 建设网站平台需要的设备排行榜前十名
  • 手机网站后台源码小时seo
  • 这么自己做网站深圳seo优化方案
  • 政府网站 banner 源码网络营销策划书总结
  • 外贸商做英文网站的目的石家庄百度关键词优化
  • 如何建设电子商务网站软文推广渠道主要有
  • 旅游网站开发景点数据库googleplay官方下载
  • 网站后台管理系统如何安装搜索引擎优化方法有哪些
  • 旅游营销型网站建设成都新一轮疫情
  • 专业积分商城网站建设吸引顾客的营销策略
  • 企业网站备案需要什么资料seo公司杭州
  • 网站https认证怎么做如何自己建个网站
  • 肇庆建设银行招聘网站微营销系统
  • 网站平台建设属于固定资产吗搜索引擎广告投放
  • 专业的网站首页建设公司设计网络推广方案
  • 专门做护肤品网站计算机培训班
  • 深圳网站定制深圳网站建设公司漯河网络推广哪家好
  • 怎么做谷歌这样的网站吗怎么做好销售
  • 做网站批发利润怎么样网站建设平台软件
  • 上海易站网站建设山西疫情最新情况
  • 怎么查看网站的外链进入百度知道首页
  • 郑州市住房和城乡建设委员会网站最新行业动态
  • 汉网网站建设今日国内新闻最新消息10条新闻
  • 深圳创业项目资源网站排名优化seo
  • 长宁专业做网站杭州上城区抖音seo有多好
  • 用什么技术可以做web网站如何推广app赚钱
  • 上海网站建设推荐q479185700顶你品牌营销的四大策略