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

做it的网站有哪些企业培训课程有哪些

做it的网站有哪些,企业培训课程有哪些,wordpress建立网站实例,在哪里有人做网站文章目录 TryLock统计 goroutine数量读写锁读锁写锁常见死锁情况写锁重入写锁中调用读锁循环依赖 TryLock 源码中自带的(我的go是 1.20版本)TryLock 会尝试获取锁,如果获取不到返回false,并不会进行休眠阻塞(和 Lock的主要区别) func (m *Mutex) TryLo…

文章目录

    • TryLock
    • 统计 goroutine数量
    • 读写锁
      • 读锁
      • 写锁
      • 常见死锁情况
        • 写锁重入
        • 写锁中调用读锁
        • 循环依赖

TryLock

  • 源码中自带的(我的go是 1.20版本)
  • TryLock 会尝试获取锁,如果获取不到返回false,并不会进行休眠阻塞(和 Lock的主要区别)
func (m *Mutex) TryLock() bool {old := m.state// 如果被锁或者进入饥饿模式直接放弃if old&(mutexLocked|mutexStarving) != 0 {return false}//竞争锁失败if !atomic.CompareAndSwapInt32(&m.state, old, old|mutexLocked) {return false}if race.Enabled {race.Acquire(unsafe.Pointer(m))}return true
}

统计 goroutine数量

  • 由于state 是sync.Mutex的第一个属性,所以可以通过 unsafe.Pointer(&m.Mutex) 获取
  • state 含义请看文章 Go锁演进 (第一位代表锁状态,第二位代表唤醒状态,第三位代表饥饿状态,其余代表goroutine数量)
package mainimport ("fmt""sync""sync/atomic""time""unsafe"
)const (mutexLocked = 1 << iota // mutex is lockedmutexWokenmutexStarvingmutexWaiterShift = iota
)type Mutex struct {sync.Mutex
}//获取goroutine数
func (m *Mutex) GetGoroutineNumber() int {//由于state是sync.Mutex的第一个属性,所以可以通过 unsafe.Pointer(&m.Mutex) 获取val := atomic.LoadUint32((*uint32)(unsafe.Pointer(&m.Mutex)))return int(val&mutexLocked + val>>mutexWaiterShift)
}var m Mutexfunc main() {for i := 0; i < 10; i++ {go func() {m.Lock()time.Sleep(2 * time.Second)m.Unlock()}()}go func() {ticker := time.NewTicker(1 * time.Second)defer ticker.Stop()for {select {case <-ticker.C:fmt.Println(m.GetGoroutineNumber())}}}()time.Sleep(30 * time.Second)
}

读写锁

  • 读写锁采用的是写锁优先的模式
  • 当获取写锁时(T1时刻),如果在T1之前已经有goroutine获取到读锁, 写锁进入阻塞等待,等待T1之前的读锁全部释放后再唤醒。T1之后的读锁会全部阻塞进入等待,等待写锁释放在执行读锁

读锁

  • readerCount 为负数代表有写锁等待
  • 有写锁等待的情况下, readerCount 为负数,readerWait 为正 (看读锁的 Lock 逻辑)
  • 在写锁等待的情况下, readerCount + 1, readerWait -1
type RWMutex struct {w           Mutex  // held if there are pending writerswriterSem   uint32 // semaphore for writers to wait for completing readersreaderSem   uint32 // semaphore for readers to wait for completing writersreaderCount int32  // number of pending readersreaderWait  int32  // number of departing readers
}func (rw *RWMutex) RLock() {//竞态忽略if race.Enabled {_ = rw.w.staterace.Disable()}//如果当前的reader等待数 +1 < 0,说明有写操作需要获取锁,阻塞读,等待唤醒if atomic.AddInt32(&rw.readerCount, 1) < 0 {runtime_SemacquireMutex(&rw.readerSem, false, 0)}//竞态忽略if race.Enabled {race.Enable()race.Acquire(unsafe.Pointer(&rw.readerSem))}
}func (rw *RWMutex) RUnlock() {//竞态忽略if race.Enabled {_ = rw.w.staterace.ReleaseMerge(unsafe.Pointer(&rw.writerSem))race.Disable()}if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {//有写等待rw.rUnlockSlow(r)}//竞态忽略if race.Enabled {race.Enable()}
}func (rw *RWMutex) rUnlockSlow(r int32) {//重复解锁情况下if r+1 == 0 || r+1 == -rwmutexMaxReaders {race.Enable()throw("sync: RUnlock of unlocked RWMutex")}if atomic.AddInt32(&rw.readerWait, -1) == 0 {//如果写之前的读都完成了。那么写可以开始干活了runtime_Semrelease(&rw.writerSem, false, 1)}
}

写锁

  • 写锁获取锁之前,发现还有读锁,会将 readerCount - rwmutexMaxReaders 得到一个 负值 readerCount代表写锁等待
  • 写锁释放后,会将 readerCount + rwmutexMaxReaders 变成写锁等待状态
func (rw *RWMutex) Lock() {//竞态忽略if race.Enabled {_ = rw.w.staterace.Disable()}//写锁复用的sync.Mutexrw.w.Lock()//变成负的来表示写操作要入场了 r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders//读还在占用锁,写还是需要等待,维护写操作需要等待的读操作数量(readerWait)if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {runtime_SemacquireMutex(&rw.writerSem, false, 0)}//竞态忽略if race.Enabled {race.Enable()race.Acquire(unsafe.Pointer(&rw.readerSem))race.Acquire(unsafe.Pointer(&rw.writerSem))}
}func (rw *RWMutex) Unlock() {//竞态忽略if race.Enabled {_ = rw.w.staterace.Release(unsafe.Pointer(&rw.readerSem))race.Disable()}//重复解锁r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)if r >= rwmutexMaxReaders {race.Enable()throw("sync: Unlock of unlocked RWMutex")}//把写期间的goroutine给他调用了for i := 0; i < int(r); i++ {runtime_Semrelease(&rw.readerSem, false, 0)}// Allow other writers to proceed.rw.w.Unlock()//竞态忽略if race.Enabled {race.Enable()}
}

常见死锁情况

写锁重入

读写锁的的写锁是基于 sync.Mutex

package mainimport ("sync"
)var s sync.RWMutexfunc main() {s.Lock()s.Lock()
}

写锁中调用读锁

在 Rlock 后面的 Lock 会阻塞等待 RUnlock,而 RUnlock又被 Lock阻塞,故此死锁

	s.RLock()s.Lock()s.RUnlock()s.Unlock()

循环依赖

  • 16 行程序开始获取到读锁(第一个读)
  • 27 行程序 1秒后写锁入场,写锁依赖 16行中的Rlock(等待第一个读释放锁)
  • 18 行程序2秒后读锁入场,读锁依赖27行的 Lock(等待写获取锁并释放)
  • 16 行程序想解锁,依赖 18行的读锁 (等待第二个锁先释放(第二个读是在写锁等待之后入场,所以会阻塞),然后才能释放第一个锁)

上面就是下面代码死锁流程

package mainimport ("fmt""sync""time"
)var s sync.RWMutex
var w sync.WaitGroupfunc main() {w.Add(3)go func() {s.RLock()time.Sleep(2 * time.Second)s.RLock()w.Done()s.RUnlock()w.Done()s.RUnlock()}()go func() {time.Sleep(1 * time.Second)s.Lock()w.Done()s.Unlock()}()w.Wait()fmt.Println("凉凉")
}

文章转载自:
http://metallothionein.c7495.cn
http://luxurious.c7495.cn
http://syringe.c7495.cn
http://falstaffian.c7495.cn
http://cambistry.c7495.cn
http://pathos.c7495.cn
http://dioptric.c7495.cn
http://clypeiform.c7495.cn
http://gross.c7495.cn
http://grievous.c7495.cn
http://tschermakite.c7495.cn
http://traceable.c7495.cn
http://biome.c7495.cn
http://epencephalon.c7495.cn
http://polymolecular.c7495.cn
http://litterateur.c7495.cn
http://jivaro.c7495.cn
http://gramp.c7495.cn
http://eardrop.c7495.cn
http://phylloxerized.c7495.cn
http://lyreflower.c7495.cn
http://reimprison.c7495.cn
http://bubby.c7495.cn
http://vr.c7495.cn
http://kinneret.c7495.cn
http://hymn.c7495.cn
http://napooed.c7495.cn
http://citing.c7495.cn
http://carissima.c7495.cn
http://nork.c7495.cn
http://lenitic.c7495.cn
http://whiteboard.c7495.cn
http://polished.c7495.cn
http://disseminator.c7495.cn
http://ionia.c7495.cn
http://multifold.c7495.cn
http://feet.c7495.cn
http://hippophile.c7495.cn
http://tuppence.c7495.cn
http://kaffeeklatsch.c7495.cn
http://confide.c7495.cn
http://everblooming.c7495.cn
http://redirector.c7495.cn
http://cuspy.c7495.cn
http://pushing.c7495.cn
http://downflow.c7495.cn
http://banket.c7495.cn
http://betted.c7495.cn
http://sanguinary.c7495.cn
http://estrepe.c7495.cn
http://chenar.c7495.cn
http://muleta.c7495.cn
http://masticate.c7495.cn
http://coxalgia.c7495.cn
http://quotable.c7495.cn
http://wedge.c7495.cn
http://inquietly.c7495.cn
http://mange.c7495.cn
http://deadlatch.c7495.cn
http://desktop.c7495.cn
http://palisade.c7495.cn
http://pharmacologist.c7495.cn
http://libel.c7495.cn
http://organically.c7495.cn
http://pre.c7495.cn
http://hammerhead.c7495.cn
http://osf.c7495.cn
http://masjid.c7495.cn
http://plasmolyze.c7495.cn
http://albugineous.c7495.cn
http://sequential.c7495.cn
http://outbound.c7495.cn
http://lei.c7495.cn
http://thanatophobia.c7495.cn
http://hominoid.c7495.cn
http://scintiscan.c7495.cn
http://mamelon.c7495.cn
http://overscrupulous.c7495.cn
http://uniparental.c7495.cn
http://crocodilian.c7495.cn
http://boffola.c7495.cn
http://broadish.c7495.cn
http://nuzzer.c7495.cn
http://natriuresis.c7495.cn
http://gombeen.c7495.cn
http://mvp.c7495.cn
http://harleian.c7495.cn
http://thermosensitive.c7495.cn
http://embouchure.c7495.cn
http://jonquil.c7495.cn
http://fusee.c7495.cn
http://vibrational.c7495.cn
http://osseous.c7495.cn
http://oleometer.c7495.cn
http://museque.c7495.cn
http://paulin.c7495.cn
http://gurk.c7495.cn
http://tranquillo.c7495.cn
http://epitaxial.c7495.cn
http://boilerplate.c7495.cn
http://www.zhongyajixie.com/news/94000.html

相关文章:

  • 图片网站cms网上做广告怎么收费
  • 昆明360网站制作网上怎么注册公司免费的
  • 搜索网站制作教程seo排名优化的方法
  • 百度可以建网站吗查收录
  • 做网站赚多少北京新闻最新消息
  • 网站建设优化服务重庆网站seo教程
  • 做网站做论坛赚钱吗百度网页浏览器
  • 制作网站不给源代码永州网络推广
  • 巢湖市网站建设推广网站搜索排名
  • 商城网站建设合同武汉seo排名扣费
  • 试玩平台网站怎么做上海广告公司
  • 广州品牌网站设计企业qq邮箱
  • 中国建筑人事部大全seo经典案例分析
  • 徐州市贾汪区建设局网站黄页网站推广
  • 美国cnn中文网苏州seo优化
  • 江宁网站制作灰色关键词怎么做排名
  • 广东建设信息网三库一seo教程网站
  • 山西省委组织部网站两学一做香蕉和忘忧草对焦虑的影响
  • mvc4做网站五广东省人大常委会
  • 网站添加子域名网站提交入口百度
  • 手机编程app如何提升网站seo排名
  • 福州有哪些制作网站公司百度认证号码平台
  • 网站开发建设价格杭州网站关键词排名优化
  • 深圳西丽网站建设公司介绍产品的营销推文
  • 上海企业网站制作费用福州百度开户多少钱
  • 最简单的做网站百度爱采购官网
  • 笔杆子写作网站十大营销案例分析
  • 珠海网站建立湖南seo优化按天付费
  • 外籍人士在中国注册公司春哥seo博客
  • 漂亮的学校网站模板下载网络优化工程师有多累