Go 如何在内部锁定对所有结构字段的并发访问?
如何在内部锁定对所有结构字段的并发访问?假设我有一个结构:Go 如何在内部锁定对所有结构字段的并发访问?,go,Go,如何在内部锁定对所有结构字段的并发访问?假设我有一个结构: type Data struct { ID string Size int //... and more fields } 将在另一个结构中使用的: type Project struct { mu sync.Mutex MetaData Data //... and more fields } 如何修改/获取元数据结构并使用互斥体,同时不向外部包公开其互斥体?我知道我可以使用Ge
type Data struct {
ID string
Size int
//... and more fields
}
将在另一个结构中使用的:
type Project struct {
mu sync.Mutex
MetaData Data
//... and more fields
}
如何修改/获取元数据结构并使用互斥体,同时不向外部包公开其互斥体?我知道我可以使用Get/Set方法,但是如果我需要修改Data struct的一个字段(如果每个字段都有一个具有相同共享互斥体的Get/Set方法,那就不是很好/干净了)该怎么办?您能推荐一种方法/模式,使结构式互斥锁在内部被锁定/解锁吗?类似的方法如何
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)
}
像这样的怎么样
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)
}
我对此很好奇,所以我测试了这个,如果父结构被锁定,子结构也被锁定。在当地尝试一下,因为围棋场似乎是确定的
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)
}
主程序包
进口(
“fmt”
“同步”
)
类型testGroup结构{
同步互斥
项目映射[字符串]*测试
}
类型测试结构{
x int
}
var str string=“测试”
func增量(t*testGroup,wg*sync.WaitGroup){
t、 锁()
t、 项目[str].x=t.items[str].x+1
t、 解锁()
wg.Done()
}
func main(){
var w sync.WaitGroup
tg:=testGroup{}
tg.items=make(映射[字符串]*测试)
tg.items[str]=&test{}
对于i:=0;i<1000;i++{
w、 加(1)
go增量(&tg,&w)
}
w、 等等
fmt.Println(“x的最终值”,tg.items[str].x)
}
尝试在
increment()
函数中注释t.Lock()
和t.Unlock()
我对此很好奇,所以我测试了这个,如果父结构被锁定,子结构也会被锁定。在当地尝试一下,因为围棋场似乎是确定的
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)
}
主程序包
进口(
“fmt”
“同步”
)
类型testGroup结构{
同步互斥
项目映射[字符串]*测试
}
类型测试结构{
x int
}
var str string=“测试”
func增量(t*testGroup,wg*sync.WaitGroup){
t、 锁()
t、 项目[str].x=t.items[str].x+1
t、 解锁()
wg.Done()
}
func main(){
var w sync.WaitGroup
tg:=testGroup{}
tg.items=make(映射[字符串]*测试)
tg.items[str]=&test{}
对于i:=0;i<1000;i++{
w、 加(1)
go增量(&tg,&w)
}
w、 等等
fmt.Println(“x的最终值”,tg.items[str].x)
}
请尝试在
increment()
函数中注释出t.Lock()
和t.Unlock()
,小心,这不会锁定访问!这将在获取指针所需的时间内建立一个锁,然后解锁并返回指针,允许调用方对数据进行并发访问(包括写入),而无需任何锁定。是的,函数必须协作,只在函数执行时访问数据,而不保存指针。但是,只要你传递的函数行为正确,它就会执行OP所要求的操作。是否保存指针无关紧要。它可以调用AccessMetaData()!这将在获取指针所需的时间内建立一个锁,然后解锁并返回指针,允许调用方对数据进行并发访问(包括写入),而无需任何锁定。是的,函数必须协作,只在函数执行时访问数据,而不保存指针。但是,只要你传递的函数行为正确,它就会执行OP所要求的操作。是否保存指针无关紧要。它可以调用AccessMetaData().Size
并且Size
的读取将在AccessMetaData
中的互斥锁之外执行,而AccessMetaData
不会返回任何内容。