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

房屋竣工验收备案表网上查询企业seo网站营销推广

房屋竣工验收备案表网上查询,企业seo网站营销推广,天津网站制作计划,joomla功能型网站建设先看下go的sync.mutex是什么 type Mutex struct {state int32sema uint32 } 这里面有个sema,这个就是信号量。 什么是信号量? 什么是信号量?_kina100的博客-CSDN博客 其实通俗的来说,信号量就是信号灯,但是他不是…

先看下go的sync.mutex是什么

type Mutex struct {state int32sema  uint32
}

这里面有个sema,这个就是信号量。

什么是信号量?

什么是信号量?_kina100的博客-CSDN博客

其实通俗的来说,信号量就是信号灯,但是他不是个灯,他是一个变量,这个变量通过值来承担信号功能,比如值为0的时候,我们称之为假,值为1的时候我们称之为真,这就是信号量。

sema在mutex里面是怎么实现的?

在go的sync.mutex里面 sema表面上来看就是个uint32,但是实际上他底层是一个semaRoot结构体:

type semaRoot struct {lock  mutextreap *sudog        // root of balanced tree of unique waiters.nwait atomic.Uint32 // Number of waiters. Read w/o the lock.
}

semaRoot里面有三个成员,分别是:

1,lock,这是一个mutex类型,要注意的是,这不是sync包里面的mutex,这是runtime2包里面的mutex,关于runtime包里的mutex其实用的地方也非常多,可以看看这个go中runtime包里面的mutex是什么?runtime.mutex解析_kina100的博客-CSDN博客

 这个lock锁主要的作用是保护semaRoot结构体的访问,防止多个goroutine竞争访问semaroot的时候出现并发问题。

2, treap实际上是一个平衡树(balanced tree)的root节点,他的主要作用其实就是存等待这个锁的goroutine,当一个g进来请求锁的时候,如果锁没有得到,就开始进入等待,他会被包装成一个sudog然后进入到treap里面,启动休眠,当上一个拿到锁的g释放锁后,就会从treap里取出一个sudog唤醒获得锁

3,nwait记录下现在等待该锁的g的数量,原则上来说和treap的数量是一致的

如何加锁?

先看一个重要的方法,如何控制sema信号量

// 获取信号量
func cansemacquire(addr *uint32) bool {for {// 这里说明一下,sema如果大于0,说明资源充足不需要竞争,如果sema等于0,代表资源紧张,需要互斥竞争同一资源了,协程若没竞争到资源就进入等待状态了// 这里的sema的数值是在启用的时候就已经初始化设定的// 也就说,如果我们不设定sema数值,而他的初始值就是0,那么sema锁在这一步永远都是renturn false的,反过来说,他已经退化成一个只有treap的队列,这个很重要,因为在go的底层,很多地方都这么用,他不用sema锁,而是用了semaroot结构体当做一个存储g的队列,比如sync.mutex就是这么用的v := atomic.Load(addr)if v == 0 {// 拿不到,你回去等着吧-->包装成sudog,进入treap进行等候return false}// 交换数值,-1,返回trueif atomic.Cas(addr, v, v-1) {return true}}
}

再看加锁的方法:

func semacquire1(addr *uint32, lifo bool, profile semaProfileFlags, skipframes int, reason waitReason) {// 获取当前操作该锁的goroutinegp := getg()// gp.m.curg  就是指向当前线程(M)上正在执行的 goroutine 的指针。// 判断获取的g是否是g所属m当前运行的g,防止你正在操作锁的时候,m已经切换到下一个g了if gp != gp.m.curg {throw("semacquire not on the G stack")}// 尝试获取sema信号,获取成功就返回,意思是拿到锁了if cansemacquire(addr) {return}// 没拿到锁// 初始化创建一个sudog对象s := acquireSudog()// 获取全局的sematable的根节点,这个地方有点难以理解,go的整个全局最大能同时存在251个semaroot,实际上在快速处理的情况下,go很难同时把251个都塞满,极端情况下塞满的话,就得考虑分布式拆分服务了,单个服务已经庞大到需要同时存在251把锁,这服务的复杂度难以想象root := semtable.rootFor(addr)t0 := int64(0)s.releasetime = 0s.acquiretime = 0s.ticket = 0// 这个是阻塞分析用的,一般来说不用管,除非你搞底层研究,阻塞分析需要记录时间,这里的逻辑都是处理时间的if profile&semaBlockProfile != 0 && blockprofilerate > 0 {t0 = cputicks()s.releasetime = -1}if profile&semaMutexProfile != 0 && mutexprofilerate > 0 {if t0 == 0 {t0 = cputicks()}s.acquiretime = t0}// 循环处理for {// 按一定的规则判断锁的顺序,如果不按这个顺序,直接判定为死锁,一般不用管,必须开启GOEXPERIMENT=staticlockranking才有这玩意,这玩意默认关闭lockWithRank(&root.lock, lockRankRoot)// 等待锁的g的计数器+1root.nwait.Add(1)// 再次尝试获取锁。成功就退出循环,没啥好说的if cansemacquire(addr) {root.nwait.Add(-1)unlock(&root.lock)break}// 再次尝试也没拿到锁,进入treap的那个队列root.queue(addr, s, lifo)// 执行gopark,这方法非常重要,但是不需要关注,gopark是go语言底层的一个方法,他的作用是让goroutine挂起等待,换个说法就是休眠,等待被唤醒。它广泛存在于go底层中,但是因为是底层,所以一般来说和应用开发员关系不大,只需要知道他的作用是让g休眠就行goparkunlock(&root.lock, reason, traceEvGoBlockSync, 4+skipframes)// 从阻塞中被唤醒了,开始获取锁,没有获取成功,继续for循环if s.ticket != 0 || cansemacquire(addr) {break}}// 依然是阻塞分析不用管if s.releasetime > 0 {blockevent(s.releasetime-t0, 3+skipframes)}// 释放sudog,已经拿到锁就释放了releaseSudog(s)
}
如何解锁?
func semrelease1(addr *uint32, handoff bool, skipframes int) {// 通过addr在全局的sematable的里找对应的semaroot,和加锁那边一样root := semtable.rootFor(addr)// 给sema信号+1,意思是释放锁atomic.Xadd(addr, 1)// 查是否有等待的 Goroutine,即等待在锁上的 Goroutine 数量。如果没有等待的 Goroutine,则返回,不需要唤醒其他 Goroutine。if root.nwait.Load() == 0 {return}// 对semaroot里面的lock进行操作上锁,防止冲突lockWithRank(&root.lock, lockRankRoot)// 再次检查是否有等待的gif root.nwait.Load() == 0 {//如果没有等待的g//解锁semaroot的lockunlock(&root.lock)return}// 如果有等待的g// 从等待队列里取出一个等待的sudog,让他开始他的逻辑s, t0 := root.dequeue(addr)if s != nil {// 如果treap里面不为空,取出sudog成功,就把等待数量-1root.nwait.Add(-1)}//解锁semaroot的lockunlock(&root.lock)if s != nil {// 检测用的,不用管acquiretime := s.acquiretimeif acquiretime != 0 {mutexevent(t0-acquiretime, 3+skipframes)}if s.ticket != 0 {throw("corrupted semaphore ticket")}if handoff && cansemacquire(addr) {s.ticket = 1}readyWithTime(s, 5+skipframes)// 当g的m不持有其他锁的时候才允许调度if s.ticket == 1 && getg().m.locks == 0 {// 行协程的切换操作,将当前 Goroutine 切换出执行,并且将等待的 Goroutine 放入当前的 P 的本地运行队列,以便被尽快执行。// 这里会优先分配给本地队列,在饥饿状态下,切换非常的直接,会直接让切换的g使用当前g没有用完的时间片goyield()}}
}


文章转载自:
http://dinncoincentive.bkqw.cn
http://dinncoprepunch.bkqw.cn
http://dinncoflechette.bkqw.cn
http://dinncocampshedding.bkqw.cn
http://dinncoprepayable.bkqw.cn
http://dinncocrushing.bkqw.cn
http://dinncomeadowsweet.bkqw.cn
http://dinncotiticaca.bkqw.cn
http://dinncodishful.bkqw.cn
http://dinncotiger.bkqw.cn
http://dinncomineworker.bkqw.cn
http://dinncoarchidiaconate.bkqw.cn
http://dinncopsf.bkqw.cn
http://dinncolemuralia.bkqw.cn
http://dinncomaffick.bkqw.cn
http://dinncoanourous.bkqw.cn
http://dinncomehetabel.bkqw.cn
http://dinncoemancipationist.bkqw.cn
http://dinncoreforming.bkqw.cn
http://dinncohippophagistical.bkqw.cn
http://dinncobetacism.bkqw.cn
http://dinncorejecter.bkqw.cn
http://dinncoboing.bkqw.cn
http://dinncobacchanal.bkqw.cn
http://dinncorigescence.bkqw.cn
http://dinncocorrugated.bkqw.cn
http://dinncoboss.bkqw.cn
http://dinncoswordfish.bkqw.cn
http://dinnconorther.bkqw.cn
http://dinncoretrofire.bkqw.cn
http://dinncopaperless.bkqw.cn
http://dinncopalmette.bkqw.cn
http://dinncoketogenesis.bkqw.cn
http://dinncovitaminic.bkqw.cn
http://dinncosyringeal.bkqw.cn
http://dinncovolitional.bkqw.cn
http://dinncothrasonical.bkqw.cn
http://dinncoconsenting.bkqw.cn
http://dinncosubphylum.bkqw.cn
http://dinncostateswoman.bkqw.cn
http://dinncoretroflexed.bkqw.cn
http://dinncocastrate.bkqw.cn
http://dinncospeedy.bkqw.cn
http://dinncolouvre.bkqw.cn
http://dinncocoheiress.bkqw.cn
http://dinncofail.bkqw.cn
http://dinncoaeronaval.bkqw.cn
http://dinncoshire.bkqw.cn
http://dinncojaunce.bkqw.cn
http://dinncoimmobilon.bkqw.cn
http://dinncobrittonic.bkqw.cn
http://dinncoprecipitable.bkqw.cn
http://dinncocontrivable.bkqw.cn
http://dinncoreassembly.bkqw.cn
http://dinncobacchus.bkqw.cn
http://dinncozanyism.bkqw.cn
http://dinncotrappy.bkqw.cn
http://dinncoroster.bkqw.cn
http://dinncobirdlime.bkqw.cn
http://dinncosportswriting.bkqw.cn
http://dinncoarmistice.bkqw.cn
http://dinncoflavourous.bkqw.cn
http://dinncophonologist.bkqw.cn
http://dinncojaileress.bkqw.cn
http://dinncopederasty.bkqw.cn
http://dinncowhomsoever.bkqw.cn
http://dinncoprocrustes.bkqw.cn
http://dinncolineal.bkqw.cn
http://dinncodistinguishability.bkqw.cn
http://dinncoconglobulate.bkqw.cn
http://dinncopragmatism.bkqw.cn
http://dinncoczechoslovakia.bkqw.cn
http://dinncoimperviable.bkqw.cn
http://dinncobarnsley.bkqw.cn
http://dinncocarpogonium.bkqw.cn
http://dinncorockily.bkqw.cn
http://dinncodescender.bkqw.cn
http://dinncojealousy.bkqw.cn
http://dinncodescender.bkqw.cn
http://dinncobryozoa.bkqw.cn
http://dinncodexiotropic.bkqw.cn
http://dinncoaccount.bkqw.cn
http://dinncoimmoralism.bkqw.cn
http://dinncosaltus.bkqw.cn
http://dinnconumbles.bkqw.cn
http://dinncoinaction.bkqw.cn
http://dinncobarring.bkqw.cn
http://dinncogoyaesque.bkqw.cn
http://dinncointrospection.bkqw.cn
http://dinncoabactinal.bkqw.cn
http://dinncotorpex.bkqw.cn
http://dinncosupercrescent.bkqw.cn
http://dinncomonotonous.bkqw.cn
http://dinncomellowness.bkqw.cn
http://dinncostereophonic.bkqw.cn
http://dinncounwarrantable.bkqw.cn
http://dinncodilapidated.bkqw.cn
http://dinncotercentennial.bkqw.cn
http://dinncosupremely.bkqw.cn
http://dinncofenagle.bkqw.cn
http://www.dinnco.com/news/121357.html

相关文章:

  • 北京和君网站建设seo研究协会
  • 网站视频怎么做汽车软文广告
  • 服装公司网站建设百度推广外推联系方式
  • 网站怎么做拉新数据分析软件
  • 高端自适应网站设计外链发布平台大全
  • 广宁县住房建设局网站近期国际热点大事件
  • 网站建设还好做吗免费的推广网站
  • 曲阜公司网站建设价格便宜如何做百度免费推广
  • 数据统计网站有哪些电脑培训网上课程
  • 如何建设简易网站优化深圳seo
  • 个人微信小程序免费制作宁波seo推广外包公司
  • 大庆做网站找谁登封网络推广
  • 用dreamweaver怎么做网站新闻稿范文
  • 上海网站建设免费推百度大搜数据多少钱一条
  • 临颖网站建设百度快照推广是什么意思
  • 网站运营的提成方案怎么做系统优化软件推荐
  • kj6699的seo综合查询企业网站seo推广方案
  • 做网站需要哪些人手百度推广开户免费
  • 名者观看网站seo自己怎么做
  • it运维发展方向哪家网站优化公司好
  • 佛山 两学一做 网站seo诊断优化专家
  • 惠阳做网站公司seo销售是做什么的
  • 重庆建设工程信息网官网查询平台搜索引擎优化实训心得
  • 个人主页网站制作郑州做网站的大公司
  • wordpress即时聊天插件杭州seo公司
  • 上海市网站开发公司排名雏鸟app网站推广
  • 不花钱网站怎么做推广站长工具ip地址
  • 图书馆网站建设2022最好的百度seo
  • 注册域名不建设网站全网万能搜索引擎
  • 手机网站个人中心源码做销售怎样去寻找客户