我有一个 go-routine 将对象添加到 channel 中,然后我有 4 个 go-routines 来处理 channel 的对象。处理只是将对象添加到数组。但有时,最终数组中缺少对象。所以我假设 channel 在某个时候停止收集对象。我有以下代码:
package main
import (
"log"
"sync"
)
func main() {
j := 0
for {
if j == 10 {
break
}
wg := sync.WaitGroup{}
months := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"}
hits := make(chan string)
i := 0
wg.Add(1)
go func() {
defer close(hits)
for {
if i == 25 {
wg.Done()
return
}
for _, month := range months {
hits <- month
}
i++
}
}()
temp := []string{}
for updateWorker := 1; updateWorker <= 4; updateWorker++ {
wg.Add(1)
go func() {
for hit := range hits {
temp = append(temp, hit)
}
wg.Done()
return
}()
}
wg.Wait()
log.Printf("length of temp %+v\n", len(temp))
j++
}
}
我正在使用 sync 库来同步例程。我正在循环相同的过程 10 次以测试输出是否一致。我期待这样的输出:
length of temp 175
它是 175,因为我发送 7 个月的字符串 25 次。 但是有时候输出不到175,不知道为什么。我对 go routines 有点初学者。那么有人可以帮我找到原因吗?谢谢。
最佳答案
问题是 updateWorker goroutines 都从 hits channel 收集结果(到目前为止一切正常),并且它们都将结果存储到 temp 局部变量未同步。这不行。
必须同步访问来自多个 goroutine 的所有变量(其中至少有一个是写入)。
如果您在启用竞争检测器的情况下运行它,它会发出关于数据竞争的尖叫声 (go run -race app.go)。
如果您将 updateWorker goroutines 的数量减少到 1,它会立即产生有效结果,因为这样我们就消除了您应用的单一数据竞争源:
for updateWorker := 1; updateWorker <= 1; updateWorker++ {
// ...
}
如果你想保留多个 updateWorker goroutines,它们对共享 temp 变量的访问必须同步。
用sync.Mutex :
var (
mu sync.Mutex
temp []string
)
for updateWorker := 1; updateWorker <= 4; updateWorker++ {
wg.Add(1)
go func() {
for hit := range hits {
mu.Lock()
temp = append(temp, hit)
mu.Unlock()
}
wg.Done()
return
}()
}
另请注意,在这个简单的示例中,通过使用多个 updateWorker goroutines,您将一无所获,添加上述同步(锁定)甚至会降低与仅使用其中一个 goroutines 相比的性能。
要正确分配工作和收集结果,请查看此答案:Is this an idiomatic worker thread pool in Go?
关于go routine 不从 channel 中收集所有对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46664742/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser