在golang中获取锁定内存地址而不是变量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在golang中获取锁定内存地址而不是变量相关的知识,希望对你有一定的参考价值。

我有一个名为Setter的界面。名为SetterImpl的Struct实现了这个接口并有2个setter,所有这些都设置了2个接口。

type Setter interface {
    A() *AInterface
    B() *BInterface
}
type SetterImpl struct {
    a *AInterface
    b *BInterface
}

func (s *SetterImpl) A(a *AInterface) {
    a = a
}

func (s *SetterImpl) B(b *AInterface) {
    b = b
}

func returnSetter(a *AInterface, b *BInterface) Setter {
    return &SetterImpl{a:a, b:b}
}

上述方法返回的setter在堆中(比如说SHeap)并发送到gRPC服务器。现在,我想更新SetterImpl中的a和b,以便gRPC服务器使用新值。

所以我现在有2个goroutines;一个是gRPC服务器主goroutine(比如MAIN),另一个是分叉的(比如FORKED),它只是更新setter字段。

如果我在FORKED中使用Mutex,那实际上就是添加一个fence(比如java)。它实际上并没有锁定任何变量(除了它自己)。我不希望MAIN能够在FORKED更新时读取存储在SHeap中的a和b。服务器中的API线程(goroutine)在读取SHeap中的值之前不会获取Read Mutex。那么,甚至可以做我想要实现的目标吗?如果是,我该如何实现?

答案

我不认为你可以在Go中锁定变量。您只能锁定代码部分。

m.Lock()
// do stuff
m.Unlock()

您通过使用“interface”vs“Impl”模式为您自己创造了一个问题。

只需使用常规功能,您就可以简化生活。然后你可以把锁放在一个函数中,并保证它会受到保护。

由于您正在创建接口,因此无法保证实现接口的函数的内容。

另一答案

变量无法锁定。所以我想做的事情是不可能的。我做的解决方法是将一个RWMutex添加到SetterImpl并进行操作

mux.RLock()
defer mux.RUnlock()

在SetterImpl的a和b的getter中。当我想在FORKED中设置a和b时,我使用了

mux.Lock()
defer mux.Unlock()

这样,如果FORKED获取写锁定,则此时不能获取读锁定。这是可能的,因为在SHeap中创建的RWLock字段用作全局变量(即,此互斥锁永远不会更改并传递给FORKED)

以上是关于在golang中获取锁定内存地址而不是变量的主要内容,如果未能解决你的问题,请参考以下文章

如何锁定队列变量地址而不是使用临界区?

左值与右值的根本区别在于能否获取内存地址,而能否赋值不是区分的依据

Golang指针

Golang channel 的基本使用方法

golang-指针,函数,map

golang的内存模型与new()与make()