jjzjj

go - channel 阻塞顺序

coder 2024-07-11 原文

我想了解 channel 在 golang 中的工作原理。我的代码非常简单,但输出却令人惊讶。

正如文档所述:从 channel 读取和写入 channel 会阻塞当前的 goroutine,因此我认为写入 channel 会阻塞 channel ,直到主例程产生为止。

package main

func rtn(messages chan<- string) {
    defer close(messages)

    println("p1")
    messages <- "ping1"

    //for i := 0; i < 10000000; i++ { }

    println("p2")
    messages <- "ping2"
}

func main() {
    messages := make(chan string)
    go rtn(messages)

    for msg := range messages {
        println(msg)
    }
}

我以为它会打印出来

p1
ping1
p2
ping2

但它实际上打印

p1
p2
ping1
ping2

最佳答案

你正在使用一个无缓冲的 channel ,它作为主 goroutines 和第二 goroutines 之间的同步点。

在这种情况下,你只知道当第二个协程在这里时 messages <- "ping1"主要的是在 for msg := range messages 行.因此,不能保证主循环到达 println(msg)。立即地。也就是说,与此同时,第二个 goroutine 可以继续前进并到达行 println("p2")messages <- "ping2" .

作为反例,我添加一个 channel 只是为了强制打印之间的完全同步。

package main

func rtn(messages chan<- string, syncChan chan struct{}) {
    defer close(messages)

    println("p1")
    messages <- "ping1"

    //Wait for main goroutine to print its message
    <-syncChan

    //for i := 0; i < 10000000; i++ { }

    println("p2")
    messages <- "ping2"

    //Wait for main goroutine to print its message
    <-syncChan
}

func main() {
    messages := make(chan string)
    syncChan := make(chan struct{})
    go rtn(messages, syncChan)

    for msg := range messages {
        println(msg)
        //Notify the second goroutine that is free to go
        syncChan <- struct{}{}
    }
}

它打印出你期望的输出:

p1
ping1
p2
ping2

这是生成您正在寻找的输出的另一个示例。在这种情况下,主 goroutine 被 time.Sleep() 强制阻止。 .这将使第二个 goroutine 在接收器准备好接收之前准备好发送。因此,发送方实际上会阻塞发送操作。

package main

import (
    "time"
)

func rtn(messages chan<- string) {
    defer close(messages)

    println("p1")
    messages <- "ping1"

    //for i := 0; i < 10000000; i++ { }

    println("p2")
    messages <- "ping2"
}

func main() {
    messages := make(chan string)
    go rtn(messages)

    //Put main goroutine to sleep. This will make the
    //sender goroutine ready before the receiver. 
    //Therefore it will have to actually block!
    time.Sleep(time.Millisecond * 500)

    for msg := range messages {
        println(msg)
    }
}

关于go - channel 阻塞顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56379520/

有关go - channel 阻塞顺序的更多相关文章

  1. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  2. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

  3. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

  4. ruby - 以随机顺序将数组拆分为多个数组 - Ruby - 2

    我试图在每次运行时以随机顺序将一个名称数组拆分为多个数组。我知道如何拆分它们:name_array=["bob","john","rob","nate","nelly","michael"]array=name_array.each_slice(2).to_a=>[["bob","john"],["rob","nate"],["nelly","michael"]]但是,如果我希望它每次都以随机顺序吐出它们怎么办? 最佳答案 在做同样的事情之前,打乱数组。(Array#shuffle)name_array.shuffle.each_s

  5. ruby - 根据给定顺序对数字数组进行排序 - 2

    我有两个数组。第一个数组包含排序顺序。第二个数组包含任意数量的元素。我的属性是保证第二个数组中的所有元素(按值)都在第一个数组中,而且我只处理数字。A=[1,3,4,4,4,5,2,1,1,1,3,3]Order=[3,1,2,4,5]当我对A进行排序时,我希望元素按照Order指定的顺序出现:[3,3,3,1,1,1,1,2,4,4,4,5]请注意,重复是公平的游戏。A中的元素不应更改,只能重新排序。我该怎么做? 最佳答案 >>source=[1,3,4,4,4,5,2,1,1,1,3,3]=>[1,3,4,4,4,5,2,1,1

  6. ruby - 按键数组中的顺序对 Ruby 哈希进行排序 - 2

    我有一个散列:sample={bar:200,foo:100,baz:100}如何使用sort_order中的键顺序对sample进行排序:sort_order=[:foo,:bar,:baz,:qux,:quux]预期结果:sample#=>{foo:100,bar:200,baz:100}我能想到的就是new_hash={}sort_order.each{|k|new_hash[k]=sample[k]unlesssample[k].nil?}sample=new_hash必须有更好的方法。提示?不应该出现没有值的键,即键的数量保持不变,SortHashKeysbasedonord

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

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

  8. ruby - 按字段的字母顺序对数组中的哈希进行排序 - 2

    我认为这很容易,并且已经很努力地搜索过,但似乎无法让它工作。我有以下哈希:@friends=[{"name"=>"JohnSmith","id"=>"12345"},{"name"=>"JaneDoe","id"=>"23456"},{"name"=>"SamuelJackson","id"=>"34567"},{"name"=>"KateUpton","id"=>"45678"}]我正在尝试按名称的字母顺序对其进行排序。现在我正在这样做:@friends.sort{|a,b|a[0]b[0]}但是,它只是以非字母顺序输出完整结果。 最佳答案

  9. ruby - 输出顺序 - 2

    下面的代码:defaprint"Function'a'called\n"99endprint"a=",a,"\n"产生:Function'a'calleda=99为什么function'a'called首先显示?我希望首先显示a=。 最佳答案 在将参数传递给方法之前,会对它们进行求值(这样您就有了要传递的值)。对函数a调用的评估有打印"function'a'called的副作用。这就是它首先打印的原因。 关于ruby-输出顺序,我们在StackOverflow上找到一个类似的问题:

  10. ruby - 控制多机 Vagrant block 执行顺序 - 2

    我有一个多机vagrant设置,其中包含一些我需要更改执行顺序的block。由于vagrant顺序是从外到内,最嵌套的block最后执行。我需要一种方法来使供应block更加嵌套,以便它们最后执行。我尝试添加mach.vm.define但这些block没有执行,我不明白为什么。正常执行,顺序错误Vagrant.require_version">=1.6.0"VAGRANTFILE_API_VERSION="2"require'yaml'machines=YAML.load_file('vagrant.yaml')Vagrant.configure(VAGRANTFILE_API_VER

随机推荐