如何定位死锁
发个自己常用的库: https://github.com/naivefox/foxmutex
sample:
package main
import (
"fmt"
fox "github.com/naivefox/foxmutex"
"time"
)
func main() {
fox.SetDebug(true, time.Second)
mtx := fox.Mutex{}
fmt.Println(111)
mtx.Lock()
fmt.Println(222)
go func() {
fmt.Println(333)
mtx.Lock()
fmt.Println(444)
}()
time.Sleep(time.Hour)
}package main
import (
"fmt"
fox "github.com/naivefox/foxmutex"
"time"
)
func main() {
fox.SetDebug(true, time.Second)
mtx := fox.RWMutex{}
fmt.Println(111)
mtx.Lock()
fmt.Println(222)
go func() {
fmt.Println(333)
mtx.RLock()
fmt.Println(444)
}()
time.Sleep(time.Hour)
}
-race????? 回复 2# lxyscls
-race 有用吗?你试下这段代码能用-race解决吗:package main
import (
"fmt"
"sync"
"time"
)
func main() {
mtx := sync.Mutex{}
fmt.Println(111)
mtx.Lock()
fmt.Println(222)
go func() {
fmt.Println(333)
mtx.Lock()
fmt.Println(444)
}()
time.Sleep(time.Hour)
}
本帖最后由 lxyscls 于 2017-08-31 09:45 编辑
cokeboL 发表于 2017-08-30 21:59
回复 2# lxyscls
-race 有用吗?你试下这段代码能用-race解决吗:
伦家刚把K大爷的书看完,一行代码都没写过呢{:yct57:}
But,你这个代码其实不是死锁呢,1个小时后会解开的{:yct44:} 回复 4# lxyscls
:mrgreen:我功力不够所以只能锁住它一小时,等我功力提升了把它锁time.Hour * 2你先 go get "github.com/naivefox/foxmutex"
然后直接go run 我那个代码就知道效果了:mrgreen:
回复 5# cokeboL
这个求解释
[*]为什么在Mutex.Lock和RWMutex.Lock之后还要起timer?
[*]Lock之前的timer key没有记下来,Unlock只有让它自己超时
另外就是,timer中记录log用到了另外一把锁,应该是防止log混乱的?但是这样我觉得肯定会影响真正被使用的锁的,兴许原来要死锁的,加了debug就不出了,还不如把log都buffer起来,一次性输出,由fmt.println自己去保证。
回复 6# lxyscls
1.因为你Lock()成功获取了锁,但是你很久不释放,可能也是bug,所以也做了超时的log,就比如package main
import (
"fmt"
fox "github.com/naivefox/foxmutex"
"time"
)
func main() {
fox.SetDebug(true, time.Second)
mtx := fox.Mutex{}
fmt.Println(111)
mtx.Lock()
fmt.Println(222)
time.Sleep(time.Hour)
}只调用一次Lock(),通常情况下不会锁住太久
这个库的日志是相当于Warning,具体是不是死锁由写代码的人来根据实际情况判定
回复 6# lxyscls
2. Lock之前的timer key没有记下来,Unlock只有让它自己超时
这句没太看懂。。
我弄两个timer是因为 Lock() 之前的是获取锁失败的超时告警
Lock() 之后的是获取锁成功但是超时没释放的告警
本帖最后由 cokeboL 于 2017-08-31 16:18 编辑
回复 6# lxyscls
“另外就是,timer中记录log用到了另外一把锁,应该是防止log混乱的?但是这样我觉得肯定会影响真正被使用的锁的,兴许原来要死锁的,加了debug就不出了,还不如把log都buffer起来,一次性输出,由fmt.println自己去保证。”
用到另一把锁是为了在不同的并行流中Lock()和Unlock()的时候根据自己的id来获取、存储、释放之前的timer,因为timer是放
到 mtxmutexes(这个命名应该改成mtxtimers...,懒得查找替换不打算改了) 这个全局map里,多个并行流,肯定要加锁,
go 1.9的sync包里新增了个Map类型是并发安全的,换成那个就不需要在foxmutex这里用另外一把锁了,但是看了下源码里面
还是map+mutex,感觉鸡肋sync.Map也是个鸡肋:dizzy:
还有就是,这个额外的锁只是在getLockTimer、saveLockTimer、unsaveLockTimer里使用,这几个func里可以保证这个额外
的锁对原本要来debug的锁没有影响
另外就是性能问题,这个包的锁肯定性能不好,但是只作为调试期使用帮助发现问题,我一般这样写:
package main
import (
"fmt"
fox "github.com/naivefox/foxmutex"
"time"
)
type MyMutex struct {
fox.Mutex //debug
//sync.Mutex //release
}
/* type MyMutex fox.Mutex 这样不行,好像跟time包里的有关 */
func init() {
fox.SetDebug(true, time.Second)
}
func main() {
mtx := MyMutex{}
fmt.Println(111)
mtx.Lock()
fmt.Println(222)
time.Sleep(time.Hour)
}
我对于cokeboL老师,都是抱着敬仰的态度。
页:
[1]
2