标签: goroutine

你能检测出给定数量的goroutine会创建多少个线程?

我知道goroutine被多路复用到多个OS线程上,因此如果应该阻塞,例如在等待I/O时,其他人继续运行.但有没有办法提前知道如果我要创建n个goroutines我会产生多少个线程?

例如,如果我们调用下面的函数,我们就知道将为n个goroutines创建多少(或最大数量)系统线程:

type Vector []float64

// Apply the operation to n elements of v starting at i.
func (v Vector) DoSome(i, n int, u Vector, c chan int) {
    for ; i < n; i++ {
        v[i] += u.Op(v[i])
    }
    c <- 1;    // signal that this piece is done
}
Run Code Online (Sandbox Code Playgroud)

go goroutine

8
推荐指数
2
解决办法
3573
查看次数

打印到stdout导致goroutine被阻止运行?

作为一个愚蠢的基本线程练习,我一直在尝试在golang中实现睡眠理发师问题.有了频道,这应该很容易,但我遇到了一个heisenbug.也就是说,当我尝试诊断它时,问题就消失了!

考虑以下.该main()函数将整数(或"客户")推送到shop通道上.barber()读取shop频道以削减"顾客"的头发.如果我fmt.Printcustomer()函数中插入一个语句,程序将按预期运行.否则,barber()永远不要削减任何人的头发.

package main

import "fmt"

func customer(id int, shop chan<- int) {
    // Enter shop if seats available, otherwise leave
    // fmt.Println("Uncomment this line and the program works")
    if len(shop) < cap(shop) {
        shop <- id
    }
}

func barber(shop <-chan int) {
    // Cut hair of anyone who enters the shop
    for {
        fmt.Println("Barber cuts hair of customer", <-shop)
    }
}

func …
Run Code Online (Sandbox Code Playgroud)

concurrency go goroutine

7
推荐指数
1
解决办法
1170
查看次数

阻止时,渠道是否保留订单?

我有一些频道都收到相同的消息:

func broadcast(c <-chan string, chans []chan<- string) {
    for msg := range c {
        for _, ch := range chans {
            ch <- msg
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,由于每个通道chans都可能以不同的速率读取,因此当我得到一个慢的消费者时,我不想阻止其他通道.我用goroutines解决了这个问题:

func broadcast(c <-chan string, chans []chan<- string) {
    for msg := range c {
        for _, ch := range chans {
            go func() { ch <- msg }()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,传递给每个通道的消息顺序很重要.我看了一下规范,看看频道在封锁时是否保留了顺序,而我发现的只是:

如果容量大于零,则通道是异步的:如果缓冲区未满(发送)或非空(接收),则通信操作成功而不阻塞,并且按发送顺序接收元素.

对我来说,如果写入被阻止,那么它不会被"发送",而是等待被发送.有了这个假设,上面没有说明多个goroutine在写入时被阻止的发送顺序.

在通道被解除阻塞后,是否有关于发送顺序的保证?

channel go goroutine

7
推荐指数
1
解决办法
1057
查看次数

使用Goroutines在http处理程序中进行后台工作

我以为我找到了一种简单的方法来立即返回http响应,然后在后台进行一些工作而不会阻塞.但是,这不起作用.

func MyHandler(w http.ResponseWriter, r *http.Request) {
    //handle form values
    go doSomeBackgroundWork() // this will take 2 or 3 seconds
    w.WriteHeader(http.StatusOK)
}
Run Code Online (Sandbox Code Playgroud)

它第一次工作 - 立即返回响应并开始后台工作.但是,任何进一步的请求都会挂起,直到后台goroutine完成.有没有更好的方法来执行此操作,这不涉及设置消息队列和单独的后台进程.

go goroutine

7
推荐指数
2
解决办法
3842
查看次数

Golang:避免竞争条件

在Go中防止种族状况有哪些好的做法?

我能想到的唯一一个就是不在goroutine之间共享数据 - 父goroutine发送一个对象的深层副本而不是对象本身,所以child goroutine不能改变父对象的内容.这将消耗更多的堆内存,但另一种方法是学习Haskell:P

编辑:同样,是否有任何情况我上面描述的方法仍然可以遇到竞争条件?

deep-copy go race-condition goroutine

7
推荐指数
2
解决办法
5406
查看次数

Golang:为什么os.Exit在goroutines中不起作用

我有一个非常简单算法的研究计划.当成功来临时,goroutine应该通过os.Exit(0)关闭(结束).我等了一天,两天......什么?:)

这是简单的代码

package main

import "os"

func main() {
    for {
        go func() { os.Exit(0) }()
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 为什么os.Exit不会终止goroutine?
  2. 什么是终止(停止)goroutine执行的正确方法?

游乐场:http://play.golang.org/p/GAeOI-1Ksc

go goroutine

7
推荐指数
2
解决办法
2959
查看次数

Goroutine是协作调度的。这是否意味着不产生执行结果的goroutine将导致goroutine逐一运行?

来自:http : //blog.nindalf.com/how-goroutines-work/

由于goroutine是协同调度的,因此不断循环的goroutine会使同一线程上的其他goroutine饿死。

Goroutine很便宜,并且如果被阻塞,不会导致对其进行复用的线程阻塞

  • 网络输入
  • 睡眠
  • 渠道运营或
  • 阻止同步包中的原语。

因此,根据上述内容,假设您有类似这样的代码,除了循环随机次数并打印总和之外,什么也不做:

func sum(x int) {
  sum := 0
  for i := 0; i < x; i++ {
    sum += i
  }
  fmt.Println(sum)
}
Run Code Online (Sandbox Code Playgroud)

如果您使用goroutines之类的

go sum(100)
go sum(200)
go sum(300)
go sum(400)
Run Code Online (Sandbox Code Playgroud)

如果只有一个线程,goroutine将一一运行吗?

multithreading scheduling go goroutine

7
推荐指数
1
解决办法
2172
查看次数

如何在Golang中使用'time.After'和'default'?

我试图理解一个简单的Golang例程代码:

package main

import (
    "fmt"
    "time"
)

func sleep(seconds int, endSignal chan<- bool) {
    time.Sleep(time.Duration(seconds) * time.Second)
    endSignal <- true
}

func main() {
    endSignal := make(chan bool, 1)
    go sleep(3, endSignal)
    var end bool

    for !end {
        select {
        case end = <-endSignal:
            fmt.Println("The end!")
        case <-time.After(5 * time.Second):
            fmt.Println("There's no more time to this. Exiting!")
            end = true
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

这很好,但为什么我不能在这个"选择"块中使用简单的默认值?像这样的东西:

for !end {
    select {
    case end = <-endSignal:
        fmt.Println("The end.")
    case <-time.After(4 * time.Second): …
Run Code Online (Sandbox Code Playgroud)

go goroutine

7
推荐指数
1
解决办法
9441
查看次数

在Golang中运行后台任务和服务器监听的最佳实践是什么?

我是Go的新手.假设我有一台服务器正在侦听HTTP请求,同时我需要检查Redis通知,以便我可以更新数据.以下是一个例子:

func checkExpire() {
    for {
        switch msg := pubSubConn.Receive().(type) {
        case redis.Message:
        ...
    }
}

server.ListenAndServe()
Run Code Online (Sandbox Code Playgroud)

简单地将checkExpiregoroutine 放入一个好的解决方案吗?

go func() {
    for {
        switch msg := pubSubConn.Receive().(type) {
        case redis.Message:
        ...
    }
}()
Run Code Online (Sandbox Code Playgroud)

go goroutine

7
推荐指数
1
解决办法
4806
查看次数

当等待组中的一个 goroutine 发生第一个错误时如何退出?

func getRecords(ctx context.Context, ids *[]Id) error {
    ctx, cancel := context.WithTimeout(ctx, DefaultTimeout)
    defer cancel()

    var wg sync.WaitGroup
    size := len(*ids)
    allErrors := make(chan error, size)

    for i := 0; i < size; i++ {
        wg.Add(1)

        go func(x int){
            err := //call to other func which return error type. nil or error
            if err != nil { // I will be creating n goroutines. How to exit rightaway if one of 
                            // them return error
                allErrors <- err 
            }
            wg.Done()
        }(i) …
Run Code Online (Sandbox Code Playgroud)

channel worker go goroutine

7
推荐指数
1
解决办法
2701
查看次数