登录
首页 >  Golang >  Go问答

检测正在使用锁的goroutine方法

来源:stackoverflow

时间:2024-03-23 12:18:30 115浏览 收藏

在使用 Storm 和数据模型进行数据库更新时,高并发下会出现 Bolt 事务提交锁等待问题。由于 Goroutine 没有外部 ID,无法直接检测占用锁的 Goroutine。这是因为锁可以在一个 Goroutine 中获取,而在另一个 Goroutine 中释放,导致难以确定是谁持有锁。因此,仅使用提供的互斥体无法看到谁占用了锁。

问题内容

我使用 echo 制作了一个 http 服务器,并使用 storm 和数据模型存储数据,如下所示:

项目1(桶) device_type_1(桶) 设备_1(kv) 设备_2(kv) device_type_2(桶) 设备_1(kv) 设备_2(kv) 项目2(桶) ...

除了更新数据库之外,收到http请求后还有一些其他事情要做,所以我使用这样的事务:

tx, err := db.begin(true)
if err != nil {
  return
}
defer tx.rollback()

// for simplicity
projectbkt := tx.from("project1")
projectbkt.save(&project)


// other things
.......


if err := tx.commit(); err != nil {
  return
}

bolt事务提交时锁等待的概率很高,堆栈如下所示:

goroutine 53 [semacquire, 5 minutes]:
sync.runtime_SemacquireMutex(0xc000002560, 0x16a7f00, 0x0)
        C:/Go/src/runtime/sema.go:71 +0x4e
sync.(*RWMutex).Lock(0xc000002558)
        C:/Go/src/sync/rwmutex.go:103 +0xc0
go.etcd.io/bbolt.(*DB).mmap(0xc0000023c0, 0x20000, 0x0, 0x0)
        D:/data/Go/pkg/mod/go.etcd.io/[email protected]/db.go:246 +0x65
go.etcd.io/bbolt.(*DB).allocate(0xc0000023c0, 0x1, 0x0, 0x0, 0x0)
        D:/data/Go/pkg/mod/go.etcd.io/[email protected]/db.go:846 +0x24b
go.etcd.io/bbolt.(*Tx).allocate(0xc000e98fc0, 0x1, 0x0, 0x0, 0x0)
        D:/data/Go/pkg/mod/go.etcd.io/[email protected]/tx.go:454 +0x79
go.etcd.io/bbolt.(*node).spill(0xc0001539d0, 0x0, 0x0)
        D:/data/Go/pkg/mod/go.etcd.io/[email protected]/node.go:368 +0x3f0
go.etcd.io/bbolt.(*Bucket).spill(0xc0001cb740, 0x0, 0x0)
        D:/data/Go/pkg/mod/go.etcd.io/[email protected]/bucket.go:541 +0x73a
go.etcd.io/bbolt.(*Bucket).spill(0xc000e98fd8, 0x0, 0x0)
        D:/data/Go/pkg/mod/go.etcd.io/[email protected]/bucket.go:508 +0x64f
go.etcd.io/bbolt.(*Tx).Commit(0xc000e98fc0, 0x0, 0x0)
        D:/data/Go/pkg/mod/go.etcd.io/[email protected]/tx.go:163 +0x1bf
github.com/asdine/storm.(*node).Commit(0xc0001cb380, 0x0, 0x0)
        D:/data/Go/pkg/mod/github.com/asdine/[email protected]+incompatible/transaction.go:46 +0x5c
.....

问题是如何检测占用锁的 goroutine 以便检查整个操作顺序?


解决方案


Goroutine 没有外部 ID。

按照设计,可以在一个 goroutine 中获取锁,并在另一个 goroutine 中释放锁。因此,如果锁定被持有,它并不是由 Goroutine 持有:任何人都可以解锁它,并且没有 ID 来记录谁锁定了它。

(因此,答案是仅使用提供的互斥体,您无法看到谁占用了它。)

今天关于《检测正在使用锁的goroutine方法》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>