[英]Does OS thread get blocked on io performed by go-routine?
On my machine there are 4 logical processors.在我的机器上有 4 个逻辑处理器。 so there are four contexts
P1
, P2
, P3
& P4
working with OS threads M1
, M2
, M3
& M4
所以有四个上下文
P1
, P2
, P3
和P4
与操作系统线程M1
, M2
, M3
和M4
一起使用
$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
In the below code:在下面的代码中:
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func getPage(url string) (int, error) {
resp, err := http.Get(url)
if err != nil {
return 0, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return 0, err
}
return len(body), nil
}
func worker(urlChan chan string, sizeChan chan<- string, i int) {
for {
url := <-urlChan
length, err := getPage(url)
if err == nil {
sizeChan <- fmt.Sprintf("%s has length %d (%d)", url, length, i)
} else {
sizeChan <- fmt.Sprintf("%s has error %s (%d)", url, err, i)
}
}
}
func main() {
urls := []string{"http://www.google.com/", "http://www.yahoo.com",
"http://www.bing.com", "http://bbc.co.uk", "http://www.ndtv.com", "https://www.cnn.com/"}
urlChan := make(chan string)
sizeChan := make(chan string)
for i := 0; i < len(urls); i++ {
go worker(urlChan, sizeChan, i)
}
for _, url := range urls {
urlChan <- url
}
for i := 0; i < len(urls); i++ {
fmt.Printf("%s\n", <-sizeChan)
}
}
there are six go-routines that perform http.Get()
有六个执行
http.Get()
的 go-routines
1) 1)
Does OS thread( M1
) get blocked with go-routine( G1
) on io( http.Get()
)? OS线程(
M1
)是否被io( http.Get()
)上的go-routine( G1
)阻塞? on context P1
在上下文
P1
or或者
Does Go scheduler pre-empt go-routine( G1
) from OS thread( M1
) upon http.Get()
? Go 调度程序是否在
http.Get()
) 上从 OS 线程 ( M1
) 抢占 go-routine ( G1
) ? and assign G2
to M1
... if yes, on pre-emption of G1
, how G1
is managed by Goruntime to resume G1
upon completion of IO( http.Get
)?并将
G2
分配给M1
...如果是,在抢占G1
时,Goruntime 如何管理G1
以在完成 IO 后恢复G1
( http.Get
)?
2) 2)
What is the api to retrieve context number(P) used for each go-routine(G)?检索用于每个 go-routine (G) 的上下文编号 (P) 的 api 是什么? for debugging purpose..
用于调试目的..
3) we maintain critical section using counted semaphore for above reader writer problem using C pthreads library. 3)我们使用计数信号量维护临界区,使用 C pthreads 库解决上述读写器问题。 Why are we not getting into the usage of critical sections using go-routines and channels?
为什么我们不使用 go-routines 和通道来使用关键部分?
No, it doesn't block.不,它不会阻塞。 My rough (and unsourced, I picked it up through osmosis) understanding is that whenever a goroutine wants to perform a "blocking" I/O that has an equivalent non-blocking version,
我粗略的(并且没有来源,我是通过 osmosis 得到的)理解是,每当一个 goroutine 想要执行一个具有等效非阻塞版本的“阻塞”I/O 时,
select
loop (or poll
or whatever equivalent is available) waiting for such operations to unblock, andselect
循环(或poll
或任何可用的等效项)中,等待此类操作解除阻塞,并且 When the I/O operation unblocks, the select-loop looks in the table to figure out which goroutine was interested in the result, and schedules it to be run.当 I/O 操作解除阻塞时,选择循环在表中查找哪个 goroutine 对结果感兴趣,并安排它运行。 In this way, goroutines waiting for I/O do not occupy an OS thread.
这样,等待 I/O 的 goroutine 就不会占用一个 OS 线程。
In case of I/O that can't be done non-blockingly, or any other blocking syscall, the goroutine executes the syscall through a runtime function that marks its thread as blocked, and the runtime will create a new OS thread for goroutines to be scheduled on.在无法以非阻塞方式完成的 I/O 或任何其他阻塞系统调用的情况下,goroutine 通过运行时 function 执行系统调用,将其线程标记为阻塞,运行时将为 goroutine 创建一个新的 OS 线程被安排在。 This maintains the ability to have GOMAXPROCS running (not blocked) goroutines.
这保持了让 GOMAXPROCS 运行(未阻塞)goroutines 的能力。 This doesn't cause very much thread bloat for most programs, since the most common syscalls for dealing with files, sockets, etc. have been made async-friendly.
对于大多数程序来说,这不会导致太多的线程膨胀,因为用于处理文件的最常见系统调用 sockets 等已变得异步友好。 (Thanks to @JimB for reminding me of this, and the authors of the helpful linked answers.)
(感谢@JimB 提醒我这一点,以及有用的链接答案的作者。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.