源码 锁 自旋 Spin go程调度顺序 死锁 读写锁 go程 均分时间片
github.com\google\gopacket@v1.1.19\pcap\pcap_windows.go
switch goroutines
// waitForPacket waits for a packet or for the timeout to expire.
func (p *Handle) waitForPacket() {
// can't use select() so instead just switch goroutines
runtime.Gosched()
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | func labLock() { log.Println( "in-0" ) var Num int var NumMax int = 4 var concurrenceRWLockNum sync.RWMutex concurrenceRWLockNum.RLock() if Num == NumMax { concurrenceRWLockNum.RUnlock() return } else { concurrenceRWLockNum.Lock() if Num < NumMax { Num++ defer func () { concurrenceRWLockNum.Lock() Num-- concurrenceRWLockNum.Unlock() }() } concurrenceRWLockNum.Unlock() concurrenceRWLockNum.RUnlock() } log.Println( "in-1" ) } |
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_SemacquireMutex(0x56c807?, 0x18?, 0x61dda0?)
C:/Program Files/Go/src/runtime/sema.go:77 +0x25
sync.(*RWMutex).Lock(0x0?)
C:/Program Files/Go/src/sync/rwmutex.go:152 +0x71
main.labLock()
/main.go:29 +0x98
} else {
main.main()
修正,调整顺序
concurrenceRWLockNum.RUnlock()
concurrenceRWLockNum.Lock()
Go\src\sync\runtime.go
// runtime_doSpin does active spinning.
func runtime_doSpin()
Go\src\sync\mutex.go
// Lock locks m.
// If the lock is already in use, the calling goroutine
// blocks until the mutex is available.
func (m *Mutex) Lock() {
// Fast path: grab unlocked mutex.
if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
if race.Enabled {
race.Acquire(unsafe.Pointer(m))
}
return
}
// Slow path (outlined so that the fast path can be inlined)
m.lockSlow()
}
// TryLock tries to lock m and reports whether it succeeded.
//
// Note that while correct uses of TryLock do exist, they are rare,
// and use of TryLock is often a sign of a deeper problem
// in a particular use of mutexes.
func (m *Mutex) TryLock() bool {
old := m.state
if old&(mutexLocked|mutexStarving) != 0 {
return false
}
// There may be a goroutine waiting for the mutex, but we are
// running now and can try to grab the mutex before that
// goroutine wakes up.
if !atomic.CompareAndSwapInt32(&m.state, old, old|mutexLocked) {
return false
}
if race.Enabled {
race.Acquire(unsafe.Pointer(m))
}
return true
}
func (m *Mutex) lockSlow() {
var waitStartTime int64
starving := false
awoke := false
iter := 0
old := m.state
for {
// Don't spin in starvation mode, ownership is handed off to waiters
// so we won't be able to acquire the mutex anyway.
if old&(mutexLocked|mutexStarving) == mutexLocked && runtime_canSpin(iter) {
// Active spinning makes sense.
// Try to set mutexWoken flag to inform Unlock
// to not wake other blocked goroutines.
if !awoke && old&mutexWoken == 0 && old>>mutexWaiterShift != 0 &&
atomic.CompareAndSwapInt32(&m.state, old, old|mutexWoken) {
awoke = true
}
runtime_doSpin()
iter++
old = m.state
continue
}
new := old
// Don't try to acquire starving mutex, new arriving goroutines must queue.
if old&mutexStarving == 0 {
new |= mutexLocked
}
if old&(mutexLocked|mutexStarving) != 0 {
new += 1 << mutexWaiterShift
}
// The current goroutine switches mutex to starvation mode.
// But if the mutex is currently unlocked, don't do the switch.
// Unlock expects that starving mutex has waiters, which will not
// be true in this case.
if starving && old&mutexLocked != 0 {
new |= mutexStarving
}
if awoke {
// The goroutine has been woken from sleep,
// so we need to reset the flag in either case.
if new&mutexWoken == 0 {
throw("sync: inconsistent mutex state")
}
new &^= mutexWoken
}
if atomic.CompareAndSwapInt32(&m.state, old, new) {
if old&(mutexLocked|mutexStarving) == 0 {
break // locked the mutex with CAS
}
// If we were already waiting before, queue at the front of the queue.
queueLifo := waitStartTime != 0
if waitStartTime == 0 {
waitStartTime = runtime_nanotime()
}
runtime_SemacquireMutex(&m.sema, queueLifo, 1)
starving = starving || runtime_nanotime()-waitStartTime > starvationThresholdNs
old = m.state
if old&mutexStarving != 0 {
// If this goroutine was woken and mutex is in starvation mode,
// ownership was handed off to us but mutex is in somewhat
// inconsistent state: mutexLocked is not set and we are still
// accounted as waiter. Fix that.
if old&(mutexLocked|mutexWoken) != 0 || old>>mutexWaiterShift == 0 {
throw("sync: inconsistent mutex state")
}
delta := int32(mutexLocked - 1<<mutexWaiterShift)
if !starving || old>>mutexWaiterShift == 1 {
// Exit starvation mode.
// Critical to do it here and consider wait time.
// Starvation mode is so inefficient, that two goroutines
// can go lock-step infinitely once they switch mutex
// to starvation mode.
delta -= mutexStarving
}
atomic.AddInt32(&m.state, delta)
break
}
awoke = true
iter = 0
} else {
old = m.state
}
}
if race.Enabled {
race.Acquire(unsafe.Pointer(m))
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | func labLock() { log.Println( "in-0" ) var wg sync.WaitGroup N := 16 wg.Add(N + N) var lk sync.RWMutex for i := 0; i < N; i++ { go func (i int) { defer wg.Done() lk.Lock() log.Println( "1=" , i) time.Sleep(2 * time.Second) lk.Unlock() }(i) } for i := 0; i < N; i++ { go func (i int) { defer wg.Done() lk.Lock() log.Println( "2=" , i) time.Sleep(2 * time.Second) lk.Unlock() }(i) } wg.Wait() log.Println( "in-1" ) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 2022/09/02 09:23:29 in-0 2022/09/02 09:23:29 1= 8 2022/09/02 09:23:31 2= 2 2022/09/02 09:23:33 1= 9 2022/09/02 09:23:35 1= 10 2022/09/02 09:23:37 1= 11 2022/09/02 09:23:39 1= 12 2022/09/02 09:23:41 1= 13 2022/09/02 09:23:43 1= 14 2022/09/02 09:23:45 1= 15 2022/09/02 09:23:47 2= 0 2022/09/02 09:23:49 2= 1 2022/09/02 09:23:51 2= 15 2022/09/02 09:23:53 2= 6 2022/09/02 09:23:55 2= 7 2022/09/02 09:23:57 2= 8 2022/09/02 09:23:59 2= 9 2022/09/02 09:24:01 2= 10 2022/09/02 09:24:03 2= 11 2022/09/02 09:24:05 2= 12 2022/09/02 09:24:07 2= 13 2022/09/02 09:24:09 2= 14 2022/09/02 09:24:11 1= 5 2022/09/02 09:24:13 2= 5 2022/09/02 09:24:15 2= 3 2022/09/02 09:24:17 1= 4 2022/09/02 09:24:19 2= 4 2022/09/02 09:24:21 1= 6 2022/09/02 09:24:23 1= 1 2022/09/02 09:24:25 1= 7 2022/09/02 09:24:27 1= 0 2022/09/02 09:24:29 1= 2 2022/09/02 09:24:31 1= 3 2022/09/02 09:24:33 in-1 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
2020-09-01 PB 级大规模 Elasticsearch 集群运维与调优实践
2018-09-01 The template root requires exactly one element
2018-09-01 微信小程序 原生代码 转wepy 字符串处理
2018-09-01 git config --system --unset credential.helper 重新输入账号密码 core.autocrlf 配置 Git 处理行结束符
2018-09-01 windows 高效配置
2018-09-01 在WePY中实现了小程序的组件化开发,组件的所有业务与功能在组件本身实现,组件与组件之间彼此隔离,上述例子在WePY的组件化开发过程中,A组件只会影响到A所绑定的myclick
2018-09-01 a