我尝试了Go Tour 练习#71
如果它运行go run 71_hang.go ok,它工作正常.
但是,如果您使用go run 71_hang.go nogood,它将永远运行.
唯一的区别是额外fmt.Print("")的default的select语句.
我不确定,但我怀疑某种无限循环和竞争条件?这是我的解决方案.
注意:Go并没有死锁 throw: all goroutines are asleep - deadlock!
package main
import (
"fmt"
"os"
)
type Fetcher interface {
// Fetch returns the body of URL and
// a slice of URLs found on that page.
Fetch(url string) (body string, urls []string, err error)
}
func crawl(todo Todo, fetcher Fetcher,
todoList chan Todo, done chan bool) { …Run Code Online (Sandbox Code Playgroud) 我有一个昂贵的功能,我应用于切片的所有项目.我正在使用goroutines来处理它,每个goroutine处理切片的一个项目.
func Huge(lst []foo) {
for _, item := range lst {
go performSlow(item)
}
// How do I synchronize here ?
return someValue(lst)
}
Run Code Online (Sandbox Code Playgroud)
问题是,如评论所示,在调用someValue函数之前,等待所有goroutine完成工作的首选方法是什么?传递一个频道performSlow并等到每个人都写到它的工作,但它似乎有点过分:
func Huge(lst []foo) {
ch := make(chan bool)
for _, item := range lst {
go performSlow(item, ch) // performSlow does its job, then writes a dummy value to ch
}
for i := range lst {
_ = <-ch
}
return someValue(lst)
}
Run Code Online (Sandbox Code Playgroud)
是否有更好的(即更有效和/或更惯用)的方式来做到这一点?
我正在关注Go Tour,当涉及到goroutines时我有点卡住了.我知道他们非常轻量级,每次goroutine阻止,另一个将开始,但我无法理解这个例子实际如何工作:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(1000 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
Run Code Online (Sandbox Code Playgroud)
据我所知,一个goroutine是针对具有参数"world"的say函数启动的,但据我所知,应该打印"world"五次并且"hello"一次.但是我不明白为什么输出是这样的:
hello
world
hello
world
hello
world
hello
world
hello
Run Code Online (Sandbox Code Playgroud)
从我对其他语言的线程的有限理解,输出应该是这样的:
hello
world
world
world
world
world
Run Code Online (Sandbox Code Playgroud)
或者像这样:
world
world
world
hello
world
world
Run Code Online (Sandbox Code Playgroud)
为什么第二行也执行五次?go语句下面的任何内容都会归类为go例程的一部分吗?
下一张幻灯片还显示了我无法再次回头看的内容:
package main
import "fmt"
func sum(a []int, c chan int) {
sum := 0 …Run Code Online (Sandbox Code Playgroud) 除非通过文件操作阻止通道通信,否则似乎不可能通过带有执行文件操作的goroutine的通道进行双向通信。我如何才能克服这种限制?
表达这个问题的另一种方式...
如果我在goroutine中运行类似于以下内容的循环,如何告诉它关闭连接并退出而不会阻塞下一个Read?
func readLines(response *http.Response, outgoing chan string) error {
defer response.Body.Close()
reader := bufio.NewReader(response.Body)
for {
line, err := reader.ReadString('\n')
if err != nil {
return err
}
outgoing <- line
}
}
Run Code Online (Sandbox Code Playgroud)
它无法从告诉它何时关闭的通道读取数据,因为它阻塞了网络读取(在我的情况下,这可能需要几个小时)。
从goroutine外部简单地调用Close()似乎并不安全,因为Read / Close方法似乎并不是完全线程安全的。
我可以简单地在例程的内部/外部使用对response.Body的引用进行锁定,但是会导致外部代码阻塞,直到挂起的读取完成为止,我特别希望能够中断正在进行的读取。
我有一个持续运行的Go程序,完全依赖于goroutines + 1 manager线程.主线程只调用goroutines然后休眠.
有内存泄漏.该程序使用越来越多的内存,直到它耗尽所有16GB RAM + 32GB SWAP,然后每个goroutine恐慌.它实际上是操作系统内存导致恐慌,通常恐慌是fork/exec ./anotherapp: cannot allocate memory我尝试执行时anotherapp.
发生这种情况时,所有工作线程都会发生混乱并恢复并重新启动.所以每个goroutine都会惊慌失措,恢复并重新启动......此时内存使用量不会减少,即使现在几乎没有任何分配,它仍然保持在48GB.这意味着所有goroutine总是会因为没有足够的内存而恐慌,直到整个可执行文件被杀死并完全重启.
整个事情大概是50,000行,但实际问题区域如下:
type queue struct {
identifier string
type bool
}
func main() {
// Set number of gorountines that can be run
var xthreads int32 = 10
var usedthreads int32
runtime.GOMAXPROCS(14)
ready := make(chan *queue, 5)
// Start the manager goroutine, which prepared identifiers in the background ready for processing, always with 5 waiting to go
go manager(ready)
// Start creating …Run Code Online (Sandbox Code Playgroud) 我有一个在多个goroutine之间共享的Golang结构.对于结构成员的并发访问,有互斥锁sync.RWMutex.对于由单个goroutine访问的struct成员,是否需要互斥保护?
例如,在下面的代码中,一个单独的writer goroutine访问成员shared.exclusiveCounter,没有任何锁定保护.这是正确/安全吗?或者是否需要互斥锁,因为整个结构由多个goroutines通过共享指针访问?
package main
import (
"fmt"
"sync"
"time"
)
func main() {
s := &shared{mutex: &sync.RWMutex{}}
readerDone := make(chan int)
writerDone := make(chan int)
go reader(s, readerDone)
go writer(s, writerDone)
<-readerDone
<-writerDone
}
type shared struct {
mutex *sync.RWMutex
sharedCounter int // member shared between multiple goroutines, protected by mutex
exclusiveCounter int // member exclusive of one goroutine -- is mutex needed?
}
func (s *shared) readCounter() int {
defer s.mutex.RUnlock()
s.mutex.RLock()
return s.sharedCounter
}
func (s *shared) …Run Code Online (Sandbox Code Playgroud) 我刚开始看看go以及go的工作原理.我只是想知道你是否可以在C++中实现相同的东西并找到boost.fiber.goroutines和boost纤维有什么区别?你能用C++中的那些光纤实现goroutine吗?
并发性是编程的一部分.最近的时间goroutine非常受欢迎.我的问题是 - 其他语言中存在哪种类似的goroutine类似物?
假设我有这个:
go func() {
for range time.Tick(1 * time.Millisecond) {
a, b = b, a
}
}()
Run Code Online (Sandbox Code Playgroud)
其他地方:
i := a // <-- Is this safe?
Run Code Online (Sandbox Code Playgroud)
对于这个问题,i与原始a或者相关的价值是不重要的b.唯一的问题是阅读a是否安全.也就是说,是否有可能a被nil部分分配,无效,未定义,......除了有效值之外的任何东西?
我试图让它失败,但到目前为止它总是成功(在我的Mac上).
在Go Go Memory Model文档中,我无法找到超出此引用的任何特定内容:
大于单个机器字的值的读取和写入表现为以未指定的顺序进行的多个机器字大小的操作.
这是否意味着单个机器字写入实际上是原子的?并且,如果是这样,函数指针写入Go单个机器字操作?
更新:这是一个正确同步的解决方案
我正在寻找一种方法来异步执行go中的两个函数,它返回不同的结果和错误,等待它们完成并打印两个结果.另外,如果函数返回错误之一,我不想等待另一个函数,只打印错误.例如,我有这个功能:
func methodInt(error bool) (int, error) {
<-time.NewTimer(time.Millisecond * 100).C
if error {
return 0, errors.New("Some error")
} else {
return 1, nil
}
}
func methodString(error bool) (string, error) {
<-time.NewTimer(time.Millisecond * 120).C
if error {
return "", errors.New("Some error")
} else {
return "Some result", nil
}
}
Run Code Online (Sandbox Code Playgroud)
这里https://play.golang.org/p/-8StYapmlg就是我实现它的方式,但我认为它有太多的代码.它可以通过使用接口{}来简化,但我不想这样做.我想要更简单的东西,例如,可以使用async/await在C#中实现.可能有一些库可以简化这种操作.
更新:感谢您的回复!我得到多快帮助真是太棒了!我喜欢WaitGroup的用法.它显然使代码对更改更加健壮,因此我可以轻松地添加另一个异步方法,而不会最终改变方法的确切数量.但是,与C#相比,仍有如此多的代码.我知道在go中我不需要明确地将方法标记为异步,使它们实际上返回任务,但是方法调用看起来要简单得多,例如,考虑这个链接实际上也需要捕获异常 顺便说一下,我找到了在我的任务中,我实际上不需要知道我想要运行异步的函数的返回类型,因为无论如何它将被整理到json,现在我只是在go-kit的端点层调用多个服务.
go ×10
goroutine ×10
concurrency ×5
channel ×2
boost ×1
c++ ×1
memory-leaks ×1
mutex ×1
select ×1