gpt4 book ai didi

c - 操作系统线程是否在 go-routine 执行的 io 上被阻塞?

转载 作者:行者123 更新时间:2023-12-01 22:39:25 27 4
gpt4 key购买 nike

在我的机器上有 4 个逻辑处理器。所以有四个上下文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

在下面的代码中:
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)
}

}

有六个执行 http.Get() 的 go-routines

1)

OS线程( M1)是否被io( G1)上的go-routine( http.Get())阻塞?根据上下文 P1
或者

Go 调度程序是否在 G1 上从 OS 线程 ( M1 ) 抢占 go-routine ( http.Get() ) ?并分配 G2M1 ...如果是,则优先于 G1 , 怎么样 G1由 Goruntime 管理以恢复 G1 IO 完成后( http.Get)?

2)

检索用于每个 go-routine(G) 的上下文编号 (P) 的 api 是什么?用于调试目的..

3) 我们使用 C pthreads 库为上述读写器问题使用计数信号量维护关键部分。为什么我们不使用 go-routines 和 channel 来使用关键部分?

最佳答案

不,它不会阻塞。我粗略的(并且没有来源,我是通过 osmosis 得到的)理解是,每当一个 goroutine 想要执行一个具有等效非阻塞版本的“阻塞”I/O 时,

  • 改为执行非阻塞版本。
  • 将它自己的 ID 记录在一个由它“阻塞”的句柄键入的表中。
  • 将完成的责任转移到位于 select 中的专用线程循环(或 poll 或任何可用的等效项)等待此类操作解除阻塞,以及
  • 挂起自身,释放其操作系统线程(M)以运行另一个 goroutine。

  • 当 I/O 操作解除阻塞时,选择循环在表中查找哪个 goroutine 对结果感兴趣,并安排它运行。这样,等待 I/O 的 goroutine 就不会占用一个 OS 线程。

    在无法以非阻塞方式完成的 I/O 或任何其他阻塞系统调用的情况下,goroutine 通过将其线程标记为阻塞的运行时函数执行系统调用,并且运行时将为 goroutines 创建一个新的 OS 线程以被安排在。这保持了让 GOMAXPROCS 运行(未阻塞)goroutines 的能力。对于大多数程序来说,这不会导致太多的线程膨胀,因为用于处理文件、套接字等的最常见的系统调用已经变得异步友好。 (感谢@JimB 提醒我这一点,以及有用的链接答案的作者。)

    关于c - 操作系统线程是否在 go-routine 执行的 io 上被阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61689829/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com