草庐IT

去原子加载和存储

coder 2023-06-26 原文

func resetElectionTimeoutMS(newMin, newMax int) (int, int) {
    oldMin := atomic.LoadInt32(&MinimumElectionTimeoutMS)
    oldMax := atomic.LoadInt32(&maximumElectionTimeoutMS)
    atomic.StoreInt32(&MinimumElectionTimeoutMS, int32(newMin))
    atomic.StoreInt32(&maximumElectionTimeoutMS, int32(newMax))
    return int(oldMin), int(oldMax)
}

我得到了这样一个go代码函数。 我感到困惑的是:为什么我们需要 atomic 在这里?这是在阻止什么?

谢谢。

最佳答案

原子函数以一种孤立的方式完成任务,其中任务的所有部分似乎都是瞬间发生或根本不发生。

在这种情况下,LoadInt32 和 StoreInt32 确保整数的存储和检索方式不会让加载的人获得部分存储。但是,您需要双方都使用原子函数才能使其正常运行。 raft示例看起来不正确至少有两个原因。

  1. 两个原子函数不能充当一个原子函数,因此在两行中读取旧的和设置新的是一种竞争条件。您可能会读取,然后其他人设置,然后您设置,并且在您设置前返回错误信息。

  2. 并非每个访问 MinimumElectionTimeoutMS 的人都在使用原子操作。这意味着在此函数中使用原子实际上是无用的。

这将如何解决?

func resetElectionTimeoutMS(newMin, newMax int) (int, int) {
    oldMin := atomic.SwapInt32(&MinimumElectionTimeoutMS, int32(newMin))
    oldMax := atomic.SwapInt32(&maximumElectionTimeoutMS, int32(newMax))
    return int(oldMin), int(oldMax)
}

这将确保 oldMin 是交换前存在的最小值。但是,整个函数仍然不是原子的,因为最终结果可能是从未使用 resetElectionTimeoutMS 调用的 oldMin 和 oldMax 对。为此……只需使用锁。

还需要更改每个函数以执行原子加载:

func minimumElectionTimeout() time.Duration {
    min := atomic.LoadInt32(&MinimumElectionTimeoutMS)
    return time.Duration(min) * time.Millisecond
}

我建议您仔细考虑一下 golang 原子文档中提到的引用 VonC:

These functions require great care to be used correctly. Except for special, low-level applications, synchronization is better done with channels or the facilities of the sync package.

如果你想了解原子操作,我建议你从http://preshing.com/20130618/atomic-vs-non-atomic-operations/开始。 .这涵盖了您的示例中使用的加载和存储操作。但是,原子还有其他用途。走吧atomic package overview复习一些很酷的东西,例如原子交换(我给出的示例)、比较和交换(称为 CAS)和添加。

我给你的链接中的一段有趣的话:

it’s well-known that on x86, a 32-bit mov instruction is atomic if the memory operand is naturally aligned, but non-atomic otherwise. In other words, atomicity is only guaranteed when the 32-bit integer is located at an address which is an exact multiple of 4.

换句话说,在当今的常见系统上,您示例中使用的原子函数实际上是空操作。它们已经是原子的了! (虽然不能保证它们,如果您需要它是原子的,最好明确指定它)

关于去原子加载和存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25519636/

有关去原子加载和存储的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  5. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  6. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  7. 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存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

  8. ruby-on-rails - 尝试设置 Amazon 的 S3 存储桶 : 403 Forbidden error & setting permissions - 2

    我正在关注Hartl的railstutorial.org并已到达11.4.4:Imageuploadinproduction.我做了什么:注册亚马逊网络服务在AmazonIdentityandAccessManagement中,我创建了一个用户。用户创建成功。在AmazonS3中,我创建了一个新存储桶。设置新存储桶的权限:权限:本教程指示“授予上一步创建的用户读写权限”。但是,在存储桶的“权限”下,未提及新用户名。我只能在每个人、经过身份验证的用户、日志传送、我和亚马逊似乎根据我的名字+数字创建的用户名之间进行选择。我已经通过选择经过身份验证的用户并选中了上传/删除和查看权限的框(而不

  9. ruby - 如何打印出 Mechanized 存储的 cookie? - 2

    我正在使用mechanize登录网站,然后检索页面。我遇到了一些问题,我怀疑这是由于cookie中的某些值造成的。当Mechanize登录网站时,我假设它存储了cookie。如何通过Mechanize打印出存储在cookie中的所有数据? 最佳答案 代理有一个cookie方法。agent=Mechanize.newpage=agent.get("http://www.google.com/")agent.cookiesagent.cookies.to_scookie返回一个Mechanize::Cookiesobject

  10. ruby-on-rails - 闪存消息存储在哪里? - 2

    我以为它们存储在cookie中-但不,检查cookie没有任何结果。session也不存储它们。那么,我在哪里可以找到它们?我需要这个来直接设置它们(而不是通过flashhash)。 最佳答案 它们存储在inyoursessionstore.自rails2.0以来的默认设置是cookie存储,但请检查config/initializers/session_store.rb以检查您是否使用默认设置以外的东西。 关于ruby-on-rails-闪存消息存储在哪里?,我们在StackOverf

随机推荐