jjzjj

go - 初始化 map 元素,其中值是具有互斥锁 golang 的结构

coder 2024-07-07 原文

我有一个映射,其中每个值都是指向另一个本身有锁的结构的指针。

type StatMap map[string]*Stats

type Stats struct {
    sync.RWMutex
    someStats, someMoreStats float64
}

我已经实现了一种方法,我将 StatMap 打包到另一个结构中并为整个 map 设置互斥锁,但我希望从数百个 goroutines 中同时修改 map 中的每个条目,因此它会更有效锁定映射中的每个元素,以便两个或多个 goroutine 可以并行读取和修改条目的值。

我想知道的是,每当出现新 key 时,我如何才能在 map 中初始化一个新条目?如果条目不在 map 中,我无法锁定该条目,并且我无法检查它是否在 map 中(据我所知)以防另一个 goroutine 当前正在修改该条目。

我不知道运行前映射中的键是什么。

我当前的实现(导致数据竞争):

initializeStatMap("key")
statMap["key"].Lock()
// . . . 


func initializeStatMap(key string) {
    if statMap[key] != nil {
        return
    }
    statMap[key] = &Stats{someStats: 0, someMoreStats: 0}
}

最佳答案

Go 的 map 语义如下:

  • map 存储(不是变量),这就是为什么这些值是 不可寻址,这就是为什么你不能做类似的事情

    type T struct {
        X int
    }
    m := make(map[int]T)
    m[0] = T{}
    m[0].x = 42 // won't compile
    
  • 这个需求主要来自 map , 一个复杂的动态数据结构,应该允许其特定的 物理移动它包含的值的实现 围绕在内存中——在进行重新平衡等操作时。

这就是为什么 map 只支持添加三个操作 (或替换)其元素,取回并删除它们。

map 对于并发使用是不安全的,所以为了做这三个中的任何一个 同时在同一张 map 上操作,你需要保护它 一种或另一种方式。

因此,一旦您从 map 中读取了一个值,编排 并发访问完全是另一回事, 在这里,我们面临着另一个关于 map 语义的事实: 因为它保留值并且可以在内存中自由复制它们, 不允许在 map 上保留任何您想拥有的东西 引用语义。例如,保留值是不正确的 您的 Stats 直接在 map 中输入——因为它们嵌入了实例 sync.Mutex,首次使用后禁止复制。 在这里,您已经通过存储指向您的指针来做正确的事情 变量。

现在你可以看到这样滚动是很OK的:

  1. 访问映射本身以获取绑定(bind)到并发安全中的键的值 方式(例如,通过持有锁)。
  2. 锁定该变量的互斥量并对其进行操作。那不 完全涉及 map 。

唯一剩下的可能问题如下。 假设您使用锁来保护对 map 的访问。 所以你捕获锁,获取绑定(bind)到键的值,通过复制 它到一个变量,释放锁并使用 值(value)。

现在,当您使用该值的副本时,另一个 goroutine 可以通过删除值或替换值来自由更新映射。

虽然在您的情况下技术上没问题 — 因为您的 map 运行于 指向变量的指针,并且可以复制指针——从程序语义的角度来看,这可能是不合适的, 这是你必须考虑清楚的事情。 为了更清楚,一旦您获得了指向 Stats 的某个实例的指针 并锁定它,可以从 map 中删除指向此实例的指针, 或者保存它的 map 条目可以由另一个指针更新—— 指向 Stats 的另一个实例,所以一旦你完成了 例如,它可能无法通过 map 到达。

关于go - 初始化 map 元素,其中值是具有互斥锁 golang 的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47433579/

有关go - 初始化 map 元素,其中值是具有互斥锁 golang 的结构的更多相关文章

  1. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  2. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  3. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  4. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  5. ruby - 在哈希的键数组中追加元素 - 2

    查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用

  6. 【高数】用拉格朗日中值定理解决极限问题 - 2

    首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有,  也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加

  7. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  8. ruby - 为什么当我调用类的实例方法时,初始化不显示为方法? - 2

    我正在写一篇关于在Ruby中几乎一切都是对象的博客文章,我试图通过以下示例来展示这一点:classCoolBeansattr_accessor:beansdefinitialize@bean=[]enddefcount_beans@beans.countendend所以从类中我们可以看出它有4个方法(当然,除非我错了):它可以在创建新实例时初始化一个默认的空bean数组它可以计算它有多少个bean它可以读取它有多少个bean(通过attr_accessor)它可以向空数组写入(或添加)更多bean(也通过attr_accessor)但是,当我询问类本身它有哪些实例方法时,我没有看到默认

  9. ruby - Hanami link_to 助手只呈现最后一个元素 - 2

    我是HanamiWorld的新人。我已经写了这段代码:moduleWeb::Views::HomeclassIndexincludeWeb::ViewincludeHanami::Helpers::HtmlHelperdeftitlehtml.headerdoh1'Testsearchengine',id:'title'hrdiv(id:'test')dolink_to('Home',"/",class:'mnu_orizontal')link_to('About',"/",class:'mnu_orizontal')endendendendend我在模板上调用了title方法。htm

  10. ruby-on-rails - 为什么在 Rails 5.1.1 中删除了 session 存储初始化程序 - 2

    我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

随机推荐