草庐IT

去例行公事被阻止

coder 2023-06-28 原文

我倾向于去,所以这可能是一个愚蠢的问题。

我似乎无法弄清楚为什么我的一个 go 例程被另一个阻止。我的理解(可能是错误的)go 例程作为独立的轻量级线程运行,因此它们不应该相互阻塞,除非我搞砸了:)

我已经粘贴了下面的代码,非常感谢任何帮助/提示来解决这个问题。

package main
import "fmt"
import "time"
import "sync"



func worker( jobs <-chan int, job2 chan<- int) {
    defer wg.Done()
    for j := range jobs {
        fmt.Println("finished job", j)
        time.Sleep(time.Second/2)

        if(j%3==0){
           job2 <- j   
        }  

   } 
   close(job2)
   fmt.Println("channel job2 closed")
 }

func worker2(job2 <-chan int) {
    defer wg.Done()
    for i:= range job2 {
        fmt.Println(i)
        time.Sleep(time.Second*10)
    } 
}

var wg sync.WaitGroup

func main() {

    wg.Add(2)
    jobs := make(chan int)

    job2 := make(chan int)

    go func() {
        for j := 1; j <= 10; j++ {
             jobs <- j
        }
        close(jobs)
        fmt.Println("channel jobs closed")
    }()

    go worker(jobs,job2)
    go worker2(job2)

    wg.Wait()
    fmt.Println("exiting main")     

}

当我运行这段代码时,我得到以下输出

finished job 1
finished job 2
finished job 3
finished job 4
3
finished job 5
finished job 6
6
finished job 7
finished job 8
finished job 9
9
finished job 10
channel jobs closed
channel job2 closed
exiting main

然而我期待这样的事情?

finished job 1
finished job 2
finished job 3
finished job 4
3
finished job 5
finished job 6
finished job 7
finished job 8
finished job 9
finished job 10
channel jobs closed
6
9    
channel job2 closed
exiting main

最佳答案

您的例程有点阻塞,因为 channel 没有缓冲。无缓冲 channel 上的写/读是阻塞操作。因此,根据定义,您的例程必须相互等待。

从本质上讲,你睡半秒是无关紧要的,因为第二个 worker 睡了 10 秒。这 10 秒将阻止对第二个 channel 的读/写。向 channel 添加缓冲区以解决此问题。

我想指出的其他一些事情是:

  • time.Sleep(time.Second/2) 不会起作用(好吧,它会起作用,但是除以 3 就不起作用)。 time.Sleep 需要一个 time.Duration 参数,它是一个 int64。您需要传递类似 time.Millisecond * 500 的内容
  • 将 channel 传递给例程并从未创建 channel 的例程中关闭它是一种不好的形式。 channel 的创建和关闭应该包含在一个例程中。如果没有,它可以工作,但维护将成为一场真正的噩梦。
  • 将您的导入分组,而不是重复 import "package",只需使用 import ( "package1"\n"package2")
  • 如非必要,请不要使用全局变量。在启动所有例程的函数中创建 WaitGroup ,并将指向它的指针传递给所有例程。包括匿名函数,只是为了安全起见(例如,一旦您开始向 channel 添加缓冲区)
  • 考虑研究 context.Contextselect 结构。您可以创建一个 context.WithCancel 并在所有例程中选择监听 ctx.Done()。然后,您可以一次性取消所有例程,而无需处理信号并将内容推送到取消 channel

演示

我更改了一些内容(主要是 channel 创建和一些次要代码清理),并创建了一个 Playground 示例 here

关于去例行公事被阻止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51360343/

有关去例行公事被阻止的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 在描述之外使用 RSpec 的 "expect"等...它会阻止 - 2

    我正在构建一个网络应用程序自动化框架,旨在允许:当然是自动化任务轻松构建测试场景我正在使用Capybara与浏览器通信,我有一个组件库,其中包含许多辅助函数(login_to_the_back_office、create_customer等)。现在我希望我的组件可以独立使用,也可以在RSpec测试中使用。这意味着我的组件(包含在库中)没有环绕describe...it...默认情况下会阻塞,但在测试使用它们时它们会在某个时候出现,因此它们应该使用expect和friend尽可能多。我关注了rspec's.shouldfails(outsidedescribe/itblock)inRub

  3. ruby-on-rails - Rails 4 - Mailer deliver_later 没有按照我的预期进行,阻止了 UI - 2

    我有一个Rails应用程序,其中有一个功能可以发送很多电子邮件。我想以异步方式的方式进行,并且我认为deliver_later方法可以做到这一点。目前,从用户单击submit到提交表单,我有一些延迟-这会导致糟糕的用户体验(这是一个非常简单的表单)。我的实现如下所示:defcreaterespond_todo|format|if@competition.save[...]send_notification_to_team_membersendenddefsend_notification_to_team_members@team.members.eachdo|member|unless

  4. ruby - 是否可以阻止 Jekyll 为每个帖子生成一个页面 - 2

    我将Jekyll用于博客/作品集网站。我有几篇文章是投资组合条目,还有几篇是博客条目。我可以使用投资组合条目帖子来构建投资组合页面(www.alexmarchant.com/portfolio),但Jekyll仍会为每个投资组合条目生成一个永久链接的单独页面。有什么办法可以关闭它吗?我在帖子的YAML前端部分尝试了以下内容:固定链接:无永久链接:错误都不行。 最佳答案 我找到了一个黑客来做你想做的事:当你将永久链接设置为一个已经存在的页面时,它就不会生成(原始页面会在那里),但它在Jekyll中仍然可以作为帖子/页面实体使用。因此,

  5. ruby-on-rails - 阻止创建一个类的多个对象 - 2

    如何将任何类的对象限制为一个。我的课看起来像:classSpeakerincludeMongoid::Documentfield:name,:type=>Stringend我只想让speaker的单个实例。一种方法是添加一个验证,该验证将检查Speaker类中已经存在的对象数量。有ruby做事的方式吗? 最佳答案 如何使用Singleton模块? 关于ruby-on-rails-阻止创建一个类的多个对象,我们在StackOverflow上找到一个类似的问题:

  6. ruby - 上帝不会阻止 unicorn - 2

    我有这个文件rails_env=ENV['RAILS_ENV']||'development'rails_root=ENV['RAILS_ROOT']||"/home/luiz/rails_dev/api"God.watchdo|w|w.name="unicorn"w.interval=30.seconds#default#unicornneedstoberunfromtherailsrootw.start="cd#{rails_root}&&unicorn_rails-cconfig/unicorn.rb-E#{rails_env}"#QUITgracefullyshutsdownw

  7. Ruby:阻止 HTTP.new.start 和动态 HTTP(S) - 2

    我需要一个应用程序来阻止HTTP请求,所以我不得不添加几行代码,唯一我想不通的是语句ifuri.scheme=='https';http.use_ssl=true有没有办法在当前语句中设置http/https:Net::HTTP.new(uri.host,uri.port).startdo|http|#CausesandIOError...ifuri.scheme=='https'http.use_ssl=trueendrequest=Net::HTTP::Get.new(uri.request_uri)http.request(request)end添加:IOError:use_ss

  8. ruby-on-rails - 有没有办法阻止 Rails 的内置服务器默认监听 0.0.0.0? - 2

    我在不受信任的网络(咖啡店、邻居的开放式wifi、DEFCON)上进行了大量的Web开发,当随机的、肯定有错误的软件(比如我正在开发的Rails应用程序)在0.0上绑定(bind)一个端口时,我会感到紧张.0.0并开始接受所有来者的请求。我知道我可以使用-b选项指定绑定(bind)到服务器的地址,但我想全局更改默认值,以便它始终以这种方式运行,除非我另有说明。当然我也可以运行某种会阻止连接的防火墙,但最好不要一开始就监听。是否有“.railsrc”文件或类似文件——至少是每个项目的设置文件,但最好是一些全局设置文件——我可以使用它来强制服务器默认仅绑定(bind)到127.0.0.1?

  9. Ruby:Phantom.js 在特定站点上被阻止? - 2

    我正在使用capybarapoltergeist来自动化tumblr.com上的一个小脚本我的脚本在我的chrome驱动程序上运行良好。我的poltergeist驱动程序加载所有其他网站都很好,但由于某种原因,当我尝试加载tumblr时抛出Capybara::Poltergeist::StatusFailError.复制步骤:$brewinstallphantomjs$geminstallcapybara$geminstallpoltergeist$geminstallselenium-webdriver$irbrequire'capybara/poltergeist'moduleDr

  10. ruby - 是什么阻止了静态类型语言拥有像 Ruby 的 method_missing 这样的东西? - 2

    我在静态类型语言方面经验不多(目前正在学习Scala并且很喜欢它!)但我注意到的一件事是它们似乎从来没有像Ruby的method_missing或ColdFusion的onMissingMethod这样的东西。静态类型语言是否有一些固有的限制来阻止或使这变得困难? 最佳答案 当然可以添加处理它们的机制,但这与静态类型不一致:编译时确定您的程序没有类型错误。附录Scala2.9引入了一个实验性选项,可以通过静态类型检查失败的方式动态处理对类型的访问。它在2.10中得到改进并成为非实验性的,尽管它仍然由默认禁用功能标志控制。您可以在SI

随机推荐