正如我们在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)
有任何想法吗?
Go运行时(调度程序,垃圾收集器等)可以使用多少个线程?例如,如果GOMAXPROCS是10,那么运行时将使用多少个内核线程?
我读的理由改变GOMAXPROCS对runtime.NumCPU()围棋1.5.有一句话声称"单个goroutine程序的性能可以通过提高GOMAXPROCS运行时的并行性来提高,特别是垃圾收集器."
我真正的问题是:如果我在具有CPU配额的Docker容器中运行单goroutine程序,那么为了获得最大性能,我需要的逻辑处理器的最小数量是多少.
我有以下代码:
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,但这看起来更像是一个丑陋的解决方法.
刚试试去吧.我想知道如果你有一个select语句等待几个频道上的通信,并且一条消息在两个或多个频道上同时出现,会发生什么.如果所有消息同时出现,select将如何确定接受哪个频道?
谢谢!
我需要从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)
我想知道有没有更好或更有惯用的方法来解决这个问题?
我是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)
它总是打印'收到两个',似乎不是随机的结果,所以我错在哪里?
代码可以在这里 …
我不明白Done()通道如何context.Context按预期工作。模块文档(和使用它的源代码)依赖于这种模式:
select {
case <-ctx.Done():
return ctx.Err()
case results <- result:
}
Run Code Online (Sandbox Code Playgroud)
Done()如果Context取消或超时,则关闭通道返回,并且Err()变量保存原因。
关于这种方法,我有两个问题:
select通道关闭时的行为是什么?案件何时以及为何进入?没有分配的事实是否具有相关性?
根据语言参考:
如果可以进行一个或多个通信,则通过统一伪随机选择选择可以进行的单个通信。
如果选择是随机的,那么该模式如何保证在Context取消时我不会将结果发送到管道中?我会理解是否按申报顺序评估案例(并选择了封闭渠道案例)。
如果我在这里完全偏离轨道,请从更好的角度向我解释这一点。
作为Windows用户,我知道操作系统线程占用大约1 Mb的内存,因为如果OS线程更加贪婪,每个内存By default, Windows allocates 1 MB of memory for each thread’s user-mode stack.如何golang使用~8kb的内存goroutine.是goroutine那种虚拟线程的?
继此答案之后,如果一个 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)
我的实验似乎表明,这对于无缓冲通道是有保证的,如图所示,但对于缓冲通道则不能保证。有人可以确认吗?
go ×9
concurrency ×6
goroutine ×4
channel ×3
channels ×1
docker ×1
idiomatic ×1
threadpool ×1
timeout ×1
windows ×1