jjzjj

go - 无法无限期地写入一个 goroutine 并从另一个 goroutine 中读取

coder 2024-07-13 原文

我正在学习围棋,但在使用 goroutines 时遇到了问题。这是我的代码

package main

import (
    "fmt"
    "sync"
    "time"
)

var counter = 0
var wg = sync.WaitGroup{}

func main() {
    ticker := time.NewTicker(time.Second)
    go func() {
        for range ticker.C {
            // wg.Add(1)
            // defer wg.Done()
            counter++
            fmt.Println(counter)
            //wg.Done()
        }
    }()

    ticker2 := time.NewTicker(time.Second * 2)
    wg.Add(1)
    go func() {
        for range ticker2.C {
            //defer wg.Done()
            fmt.Println(counter)
        }
    }()
    wg.Wait()
}

基本上,我想要:

  • 一个名为counter的全局变量
  • 一个 goroutine 每 1 秒更新一次这个计数器
  • 另一个 goroutine 每两秒打印一次这个计数器

Playground 是 here 我试着玩 WaitGroup 但我没能成功。 对于这个级别的代码,我有以下警告:

WARNING: DATA RACE
Read at 0x0000011d8318 by goroutine 8:
  runtime.convT2E64()

另一个问题这个线程安全吗?我的意思是,我可以在两个 groroutine 之外的 main 方法中安全地使用计数器吗?

最佳答案

一种方法可能是在需要打印时向第二个 gorutine 发送消息。

package main

import (
    "fmt"
    "time"
)

func main() {

    fmt.Println("Start");
    counter := 0

    printChannel := make( chan int)
    done := make(chan struct{} )

    go func(done <-chan struct{}, printChannel chan<- int  ){
        timer := time.NewTicker(time.Second)
        bDone := false;
        for !bDone {
            select {
            case <-timer.C:
                counter++
                if counter%2 == 0 {
                    printChannel <- counter
                }
            case <-done:
                bDone=true
            }
        }
    }(done, printChannel)

    go func(done <-chan struct{}, printChannel <-chan int ){
        bDone:=false
        for !bDone{
            select {
            case n := <-printChannel:
                fmt.Print(n, " ");
            case <-done:
                bDone=true
            }
        }
    }(done,printChannel)


    //whatever logic to stop
    go func() {
        <- time.After(21*time.Second)
        done <- struct{}{}
    }()

    <-done

    fmt.Println("\nEnd");

}

注意这里有第三个 gorutine 来完成这个例子

输出:

Start
2 4 6 8 10 12 14 16 18 20 
End

要改进它,您可以在没有 bDone 变量的情况下进行,您可以停止 Ticker 并在 gorutine 存在时添加适当的消息。 或者你可能想用标签测试'break'以退出循环。
您可以使用关闭(完成) channel 而不是向其发送消息来测试效果。
此外,如果您准备放宽读/写顺序,您可以删除 printChannel 并让第二个 gorutine 使用另一个每 2 秒 ping 一次的自动收报机。

关于go - 无法无限期地写入一个 goroutine 并从另一个 goroutine 中读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49617904/

有关go - 无法无限期地写入一个 goroutine 并从另一个 goroutine 中读取的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby - 树顶语法无限循环 - 2

    我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He

  3. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  4. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  5. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  6. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  7. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  8. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  9. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  10. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

随机推荐