相关疑难解决方法(0)

当在golang中写入文件时阻塞了许多goroutine时,为什么不创建多个线程?

正如我们在go中所知,当goroutine必须执行阻塞调用(例如系统调用)或通过cgo调用C库时,可能会创建一个线程.一些测试代码:

   package main

   import (
        "io/ioutil"
        "os"
        "runtime"
        "strconv"
    )

    func main() {
        runtime.GOMAXPROCS(2)
        data, err := ioutil.ReadFile("./55555.log")
        if err != nil {
            println(err)
            return
        }
        for i := 0; i < 200; i++ {
            go func(n int) {
                for {
                    err := ioutil.WriteFile("testxxx"+strconv.Itoa(n), []byte(data), os.ModePerm)
                    if err != nil {
                        println(err)
                        break
                    }
                }
            }(i)
        }
        select {}
    }
Run Code Online (Sandbox Code Playgroud)

当我运行它时,它没有创建很多线程.

? =99=[root /root]$ cat /proc/9616/status | grep -i thread
Threads:    5
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

concurrency multithreading go goroutine

9
推荐指数
2
解决办法
1799
查看次数

Go运行时使用的线程数

Go运行时(调度程序,垃圾收集器等)可以使用多少个线程?例如,如果GOMAXPROCS10,那么运行时将使用多少个内核线程?

编辑:

我读的理由改变GOMAXPROCSruntime.NumCPU()围棋1.5.有一句话声称"单个goroutine程序的性能可以通过提高GOMAXPROCS运行时的并行性来提高,特别是垃圾收集器."

我真正的问题是:如果我在具有CPU配额的Docker容器中运行单goroutine程序,那么为了获得最大性能,我需要的逻辑处理器的最小数量是多少.

concurrency multithreading go goroutine docker

9
推荐指数
1
解决办法
7642
查看次数

go select语句的强制优先级

我有以下代码:

func sendRegularHeartbeats(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        case <-time.After(1 * time.Second):
            sendHeartbeat()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此功能在专用的go-routine中执行,并每秒发送一次心跳消息.取消上下文时,整个过程应立即停止.

现在考虑以下场景:

ctx, cancel := context.WithCancel(context.Background())
cancel()
go sendRegularHeartbeats(ctx)
Run Code Online (Sandbox Code Playgroud)

这将启动具有封闭上下文的心跳例程.在这种情况下,我不希望传输任何心跳.因此,case应立即输入选择中的第一个块.

但是,似乎case无法保证评估块的顺序,并且代码有时会发送心跳消息,即使上下文已被取消.

实现这种行为的正确方法是什么?

我可以在第二个中添加"isContextclosed" - 检查case,但这看起来更像是一个丑陋的解决方法.

go

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

Golang频道选择声明

刚试试去吧.我想知道如果你有一个select语句等待几个频道上的通信,并且一条消息在两个或多个频道上同时出现,会发生什么.如果所有消息同时出现,select将如何确定接受哪个频道?

谢谢!

concurrency go channels

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

从频道阅读一段时间的惯用法

我需要从Go通道读取数据一段时间(比如说5秒).带超时的select语句对我来说不起作用,因为我需要读取尽可能多的值并在5秒后完全停止.到目前为止,我已经提出了一个使用额外时间通道的解决方案https://play.golang.org/p/yev9CcvzRIL

package main

import "time"
import "fmt"

func main() {
    // I have no control over dataChan
    dataChan := make(chan string)
    // this is a stub to demonstrate some data coming from dataChan
    go func() {
        for {
            dataChan <- "some data"
            time.Sleep(time.Second)
        }
    }()

    // the following is the code I'm asking about
    timeChan := time.NewTimer(time.Second * 5).C
    for {
        select {
        case d := <-dataChan:
            fmt.Println("Got:", d)
        case <-timeChan:
            fmt.Println("Time's up!")
            return
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想知道有没有更好或更有惯用的方法来解决这个问题?

concurrency timeout channel idiomatic go

6
推荐指数
1
解决办法
1952
查看次数

Golang`select`似乎不公平

我是Golang的初学者,我从选择的官方规范中读到,当更多的通信可以继续进行时,我会做统一的伪随机,但是当我尝试下面的代码时

package main

import (
    "fmt"
)

func main() {

    // For our example we'll select across two channels.
    c1 := make(chan string)
    c2 := make(chan string)

    go func() {
        for {
            c1 <- "one"
        }
    }()
    go func() {
        for {
            c2 <- "two"
        }
    }()

    for i := 0; i < 100; i++ {
        select {
        case msg1 := <-c1:
            fmt.Println("received", msg1)
        case msg2 := <-c2:
            fmt.Println("received", msg2)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它总是打印'收到两个',似乎不是随机的结果,所以我错在哪里?

代码可以在这里 …

concurrency go

4
推荐指数
1
解决办法
176
查看次数

选择和 context.Context Done 通道

我不明白Done()通道如何context.Context按预期工作。模块文档(和使用它的源代码)依赖于这种模式:

select {
case <-ctx.Done():
    return ctx.Err()

case results <- result:
}
Run Code Online (Sandbox Code Playgroud)

Done()如果Context取消或超时,则关闭通道返回,并且Err()变量保存原因。

关于这种方法,我有两个问题:

  1. select通道关闭时的行为是什么?案件何时以及为何进入?没有分配的事实是否具有相关性?

  2. 根据语言参考:

    如果可以进行一个或多个通信,则通过统一伪随机选择选择可以进行的单个通信。

    如果选择是随机的,那么该模式如何保证在Context取消时我不会将结果发送到管道中?我会理解是否按申报顺序评估案例(并选择了封闭渠道案例)。

如果我在这里完全偏离轨道,请从更好的角度向我解释这一点。

concurrency channel go

3
推荐指数
1
解决办法
261
查看次数

Goroutines 8kb和Windows操作系统线程1 MB

作为Windows用户,我知道操作系统线程占用大约1 Mb的内存,因为如果OS线程更加贪婪,每个内存By default, Windows allocates 1 MB of memory for each thread’s user-mode stack.如何golang使用~8kb的内存goroutine.是goroutine那种虚拟线程的?

windows multithreading go threadpool goroutine

2
推荐指数
1
解决办法
441
查看次数

select 语句能保证通道选择的顺序吗?

此答案之后,如果一个 goroutine 在两个通道上进行选择,是否可以保证以与发送通道相同的顺序选择通道?我对发件人是单线程的情况特别感兴趣。

例如,是否保证此代码始终产生相同的输出:

package main

import (
  "fmt"
  "time"
)

var x, y chan int

func worker() {
  for {
    select {
    case v := <- x:
      fmt.Println(v)
    case v := <- y:
      fmt.Println(v)
    }
  }
}

func main() {
  x = make(chan int)
  y = make(chan int)
  go worker()
  x <- 1
  y <- 2
  <- time.After(1 * time.Second)
}
Run Code Online (Sandbox Code Playgroud)

我的实验似乎表明,这对于无缓冲通道是有保证的,如图所示,但对于缓冲通道则不能保证。有人可以确认吗?

channel go goroutine

1
推荐指数
2
解决办法
95
查看次数