jjzjj

go - `make(chan _, _)` 是原子的吗?

coder 2024-07-07 原文

修改消费者正在读取的 channel 是否线程安全?

考虑以下代码:

func main(){
    channel     := make(chan int, 3)
    channel_ptr := &channel

    go supplier (channel_ptr)
    go consumer (channel_ptr)

    temp = *channel_ptr
    // Important bit
    *channel_ptr = make(chan int, 5)

    more := true
    for more{
        select {
            case msg := <-temp:
                *channel_ptr <- msg
            default:
                more = false
        }
    }
    // Block main indefinitely to keep the children alive
    <-make(chan bool)
}

func consumer(c *chan int){
    for true{
        fmt.Println(<-(*c))
    }
}

func supplier(c *chan int){
    for i :=0; i < 5; i ++{
        (*c)<-i
    }
}

如果 channel 和 make 以我希望的方式工作,我应该获得以下属性:

  1. 程序总是输出 0 1 2 3 4
  2. 程序永远不会因尝试从未初始化的 channel 读取而 panic (IE,我标记为重要位的部分是原子的)

从几次测试运行来看,这似乎是真的,但我无法在文档中的任何地方找到它,我担心微妙的竞争条件。

更新

是的,我所做的不起作用。这个线程可能在这一点上被埋没了,但是有人知道如何动态调整缓冲 channel 的大小吗?

最佳答案

它不是线程安全的。

如果您使用 -race 标志运行以使用 race detector ,你会看到错误:

$ run -race t.go
==================
WARNING: DATA RACE
Write at 0x00c420086018 by main goroutine:
  main.main()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:14 +0x128

Previous read at 0x00c420086018 by goroutine 6:
  main.supplier()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:37 +0x51

Goroutine 6 (running) created at:
  main.main()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:9 +0xb4
0
==================
1
2
3
==================
WARNING: DATA RACE
Read at 0x00c420086018 by goroutine 6:
  main.supplier()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:37 +0x51

Previous write at 0x00c420086018 by main goroutine:
  main.main()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:14 +0x128

Goroutine 6 (running) created at:
  main.main()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:9 +0xb4
==================
4

根据经验,永远不要将 channel 作为指针传递。 Channel 在内部已经是一个指针。

退后一步:我不明白你想要达到什么目的。

我想您尝试将 channel 作为指针传递是有原因的。在 Go 中使用 channel 的模式是:你创建它一次,然后将它作为值传递。您不会将指针传递给它,也不会在创建后对其进行修改。

在您的示例中,问题在于您有一 block 共享内存(channel_ptr 指向的内存地址)并且您在一个线程中写入该内存,而其他线程读取它。这就是数据竞赛。

它不是特定于 channel 的,如果它是指向 int 的指针并且两个线程正在修改 int 的值,您也会遇到同样的问题。

关于go - `make(chan _, _)` 是原子的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44974701/

有关go - `make(chan _, _)` 是原子的吗?的更多相关文章

  1. ruby-on-rails - rails : How to make a form post to another controller action - 2

    我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak

  2. ruby - 无法安装 gem - make 未被识别为内部或外部命令可运行程序或批处理文件 - 2

    我想在Windows7上安装带有ruby​​1.9.3的rspec-railsgem。我收到一些错误消息,提示无法安装某些json库。所以,我使用下面的说明来解决它。来源=The'json'nativegemrequiresinstalledbuildtools从[rubyinstaller.org][3]下载[Ruby1.9.3][2]从[rubyinstaller.org][3]下载DevKit文件对于Ruby1.9.3,使用[DevKit-tdm-32-4.5.2-20110712-1620-sfx.exe][4]将DevKit解压到路径C:\Ruby193\DevKit运行cd

  3. ruby - 当前的 Ruby 方法是通过 super 调用的吗? - 2

    在运行时的方法中,有没有办法知道该方法是否已通过子类中的super调用?例如moduleSuperDetectordefvia_super?#whatgoeshere?endendclassFooincludeSuperDetectordefbarvia_super??'super!':'nothingspecial'endendclassFu"nothingspecial"Fu.new.bar#=>"super!"我如何编写via_super?,或者,如果需要,如何编写via_super?(:bar)? 最佳答案 可能有更好的方法

  4. ruby - Ruby 导入的方法总是私有(private)的吗? - 2

    最好用一个例子来解释:文件1.rb:deffooputs123end文件2.rb:classArequire'file1'endA.new.foo将给出错误“':调用了私有(private)方法'foo'”。我可以通过执行A.new.send("foo")来解决这个问题,但是有没有办法公开导入的方法?编辑:澄清一下,我没有混淆include和require。另外,我不能使用正常包含的原因(正如许多人正确指出的那样)是因为这是元编程设置的一部分。我需要允许用户在运行时添加功能;例如,他可以说“run-this-app--includefile1.rb”,应用程序的行为将根据他在file1

  5. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  6. HarmonyOS原子化服务开发相关术语 - 2

    术语中文解释Ability原子化服务帮助用户完成任务的原子化服务,和用户的意图进行关联。Fulfillment服务履行通过图标,卡片,语音等形式呈现用户意图。开发者通过接口的方式,处理用户意图,返回内容。Intent意图用于表达用户想要达成的目标或完成的任务。HUAWEIAssistant智能助手“无微不智”的个人助手,通过不断的学习用户的使用习惯,不断的为用户提供贴心的精准的便捷的个性化服务。AISearch全局搜索用户可快速搜索关键词,与之匹配的原子化服务则会出现在搜索结果中。SmartService智慧服务用户订阅原子化服务,在到达特定触发条件(时间、地点、事件)后,卡片推送至用户智能助

  7. ruby - 无法在 MacOS 10.14.2 Mojave : Error running '__rvm_make -j4' 上使用 RVM 安装任何 Ruby - 2

    将MacOS升级到10.14.2Mojave后,我无法再使用RVM安装任何Ruby版本。它总是给出这样的错误:$rvminstall2.5.3ruby-2.5.3-#removingsrc/ruby-2.5.3..Searchingforbinaryrubies,thismighttakesometime.Nobinaryrubiesavailablefor:osx/10.14/x86_64/ruby-2.5.3.Continuingwithcompilation.Pleaseread'rvmhelpmount'togetmoreinformationonbinaryrubies.Ch

  8. ruby-on-rails - 无方法错误 : undefined method `get' when running rspec and making get/visit calls - 2

    我完全被困在这里,希望有人能指出我正确的方向。我正在尝试使用rspec来测试我的网络路由。我按照这里的例子:https://www.relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec我的规范文件被命名为:spec/requests文件夹中的api_tests_spec.rb。文件如下:require'spec_helper'describe"APITests"dodescribe"GET/regions"doit"shouldreturnavalidresponse"do#Runthegeneratoragai

  9. ruby-on-rails - ruby + Mongoid : how to make a required field? - 2

    我使用Mongoid的githead版本(因为Rails4),我想制作一个字段必填文档:classMyClassincludeMongoid::Documentfield:name,type:String,required:true我有这个错误:Problem:Invalidoption:requiredprovidedforfield:name.Summary:Mongoidrequiresthatyouonlyprovidevalidoptionsoneachfielddefinitioninordertopreventun...我做错了什么? 最佳答案

  10. ruby - 在 OSX 10.8.4 上使用无法识别的选项 '-arch' 安装 json-1.8.0 时 make 失败 - 2

    我正在尝试正确设置我的ruby​​环境,但在尝试bundleinstall我的测试应用程序时不断收到错误。我在尝试bundleinstall时第一次遇到错误:$railsnewapp//[...]runbundleinstallFetchinggemmetadatafromhttps://rubygems.org/..Resolvingdependencies...Usingrake(10.1.0)Usingi18n(0.6.5)Usingmulti_json(1.7.9)Usingactivesupport(3.2.9)Usingbuilder(3.0.4)Usingactivemo

随机推荐