如何在内部锁定对所有结构字段的并发访问?

时间:2018-03-10 21:28:14

标签: go

如何在内部锁定对所有struct字段的并发访问?让我们说我有一个结构:

 type Data struct {
    ID string
    Size int
    //... and more fields
 }

将在另一个结构中使用:

type Project struct {
    mu sync.Mutex
    MetaData Data
    //... and more fields
}

如何修改/获取MetaData结构并使用互斥锁,同时不将其互斥体暴露给外部包?我知道我可以使用Get / Set方法,但是如果我需要修改Data struct的一个字段(如果每个字段都有一个具有相同共享互斥锁的get / set方法,那么它不会非常好/干净)会怎样?你能推荐一种方式/模式来获得一个内部锁定/解锁的结构式互斥锁吗?

2 个答案:

答案 0 :(得分:2)

这样的事情怎么样?

type Data struct {
    ID   string
    Size int
    //... and more fields
}

type Project struct {
    mu       sync.Mutex
    metaData Data
    //... and more fields
}

func (p *Project) AccessMetaData(f func(*Data)) {
    p.mu.Lock()
    defer p.mu.Unlock()
    f(&p.metaData)
}

答案 1 :(得分:0)

我对此很好奇,所以我对此进行了测试,如果父结构被锁定,则子结构也被锁定。可以在游乐场尝试一下,因为它似乎是确定性的。

package main

import (
    "fmt"
    "sync"
)

type testGroup struct {
    sync.Mutex
    items map[string]*test
}

type test struct {
    x int
}

var str string = "test"

func increment(t *testGroup, wg *sync.WaitGroup) {
    t.Lock()
    t.items[str].x = t.items[str].x + 1
    t.Unlock()
    wg.Done()
}

func main() {
    var w sync.WaitGroup
    tg := testGroup{}
    tg.items = make(map[string]*test)
    tg.items[str] = &test{}
    for i := 0; i < 1000; i++ {
        w.Add(1)
        go increment(&tg, &w)
    }
    w.Wait()
    fmt.Println("final value of x", tg.items[str].x)
}

尝试在t.Lock()函数中注释掉t.Unlock()increment()