首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Golang - lock per值

Golang - lock per值
EN

Stack Overflow用户
提问于 2020-10-28 08:27:04
回答 2查看 1.2K关注 0票数 8

我正在编写一个接受tableName值和updEpoch值的golang api,即:

代码语言:javascript
复制
curl -F "tableName=abc" -F "updEpoch=123" myhost:8080/singleroute
curl -F "tableName=abc" -F "updEpoch=456" myhost:8080/singleroute
curl -F "tableName=def" -F "updEpoch=123" myhost:8080/singleroute
curl -F "tableName=def" -F "updEpoch=345" myhost:8080/singleroute

我希望允许并行处理多个不同的tableName请求,但同时每个tableName只有一个请求。因此,在上面的例子中,如果以上4个请求同时被触发,那么第一个和第三个请求应该能够同时运行(作为唯一的tableNames),但是第二个将只启动一次,第四个将只启动一次第三个完成。当我研究互斥锁时,似乎没有适合这种情况的例子,我不想在代码中的任何地方硬编码abc/def.etc,因为相同的规则应该适用于任何任意的tableName。

我的猜测是基于Crowman的帮助:

代码语言:javascript
复制
package main

import (
    "fmt"
    "sync"
    "time"
    "http"
)
km := KeyedMutex{}
type KeyedMutex struct {
    mutexes sync.Map // Zero value is empty and ready for use
}

func (m *KeyedMutex) Lock(key string) func() {
    value, _ := m.mutexes.LoadOrStore(key, &sync.Mutex{})
    mtx := value.(*sync.Mutex)
    mtx.Lock()

    return func() { mtx.Unlock() }
}

func myFunc(key string, data string) string {
  //do some stuff
  return "done for key:"+key+", data: "+data
}

func main() {
    key := //some form value sent to my api 
    data := //some form value sent to my api 
    unlock := km.Lock(key)
    defer unlock()
    retVal := myFunc(key, data)
}
EN

回答 2

Stack Overflow用户

发布于 2020-10-31 00:52:02

您可以使用表名作为键并使用*sync.Mutex作为值的sync.Map

例如:

代码语言:javascript
复制
package main

import (
    "fmt"
    "sync"
    "time"
)

type KeyedMutex struct {
    mutexes sync.Map // Zero value is empty and ready for use
}

func (m *KeyedMutex) Lock(key string) func() {
    value, _ := m.mutexes.LoadOrStore(key, &sync.Mutex{})
    mtx := value.(*sync.Mutex)
    mtx.Lock()

    return func() { mtx.Unlock() }
}

func main() {
    wg := sync.WaitGroup{}
    km := KeyedMutex{}

    for _, job := range []struct {
        key  string
        data string
    }{
        {key: "abc", data: "123"},
        {key: "abc", data: "456"},
        {key: "def", data: "123"},
        {key: "def", data: "456"},
    } {
        var job = job
        wg.Add(1)

        go func() {
            defer wg.Done()

            unlock := km.Lock(job.key)
            defer unlock()

            fmt.Printf("%s:%s mutex acquired\n", job.key, job.data)
            time.Sleep(time.Second * 1) // To ensure some goroutines visibly block
            fmt.Printf("%s:%s done\n", job.key, job.data)
        }()
    }

    wg.Wait()
}

使用示例输出:

代码语言:javascript
复制
crow@mac:$ ./mut
def:456 mutex acquired
abc:456 mutex acquired
abc:456 done
def:456 done
abc:123 mutex acquired
def:123 mutex acquired
def:123 done
abc:123 done
crow@mac:$

为了显示具有不同表名的请求立即获取互斥锁,但是具有相同表名的请求被序列化。

票数 9
EN

Stack Overflow用户

发布于 2020-10-28 08:34:05

您可以创建一个包级var mapstring*sync.Mutex并锁定相应的互斥锁,该互斥锁将通过表名获取/创建。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64564781

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档