Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Goroutines 8kb和windows OS线程1MB_Windows_Multithreading_Go_Threadpool_Goroutine - Fatal编程技术网

Goroutines 8kb和windows OS线程1MB

Goroutines 8kb和windows OS线程1MB,windows,multithreading,go,threadpool,goroutine,Windows,Multithreading,Go,Threadpool,Goroutine,作为windows用户,我知道操作系统线程消耗~1MB内存,因为默认情况下,windows为每个线程的用户模式堆栈分配1MB内存。如果操作系统线程更贪吃,那么golang如何为每个goroutine使用~8kb内存。goroutine是一种虚拟线程吗 1 MiB是默认值,正如您正确指出的那样。您可以轻松选择自己的堆栈大小(但是,最小值仍然远远高于~8 kiB) 也就是说,goroutine不是线程。它们只是具有协同多任务的任务,类似于Python。goroutine本身就是实现所需的代码和数据;

作为windows用户,我知道操作系统线程消耗~1MB内存,因为默认情况下,windows为每个线程的用户模式堆栈分配1MB内存。如果操作系统线程更贪吃,那么
golang
如何为每个
goroutine
使用~8kb内存。
goroutine
是一种虚拟线程吗

1 MiB是默认值,正如您正确指出的那样。您可以轻松选择自己的堆栈大小(但是,最小值仍然远远高于~8 kiB)

也就是说,goroutine不是线程。它们只是具有协同多任务的任务,类似于Python。goroutine本身就是实现所需的代码和数据;还有一个单独的调度器(在一个或多个OS线程上运行),它实际执行该代码

在伪代码中:

loop forever
 take job from queue
 execute job
end loop
当然,
executejob
部分可能非常简单,也可能非常复杂。您可以做的最简单的事情就是执行一个给定的委托(如果您的语言支持类似的东西)。实际上,这只是一个方法调用。例如,在更复杂的场景中,也可能会有类似于恢复某种上下文、处理连续性和协作任务产出等内容

这是一种非常轻量级的方法,在进行异步编程时非常有用(这几乎是当今的一切:)。许多语言现在都支持类似的东西——Python是我在这个(“tasklets”)中看到的第一个,这是很久以前的事了。当然,在没有先发制人多线程的环境中,这几乎是默认设置

例如,在C#中,有
Task
s。它们与goroutine并不完全相同,但在实践中,它们非常接近-主要区别在于
Task
s使用线程池中的线程(通常),而不是单独的专用“调度程序”线程。这意味着,如果启动1000个任务,它们可能由1000个单独的线程运行;实际上,它要求您编写非常糟糕的
任务
代码(例如,仅使用阻塞I/O、休眠线程、等待句柄等)。如果您使用
Task
s进行异步非阻塞I/O和CPU工作,那么在实际操作中,它们与goroutines非常接近。理论有点不同:)

编辑:

为了消除一些混淆,下面是一个典型的C#异步方法的样子:

async Task<string> GetData()
{
  var html = await HttpClient.GetAsync("http://www.google.com");

  var parsedStructure = Parse(html);
  var dbData = await DataLayer.GetSomeStuffAsync(parsedStructure.ElementId);

  return dbData.First().Description;
}
异步任务GetData() { var html=await HttpClient.GetAsync(“http://www.google.com"); var parsedStructure=Parse(html); var dbData=await DataLayer.GetSomeStuffAsync(parsedStructure.ElementId); 返回dbData.First().Description; } 从
GetData
方法的角度来看,整个处理是同步的——就好像根本没有使用异步方法一样。关键的区别在于,在进行“等待”时,您没有用完线程;但是忽略这一点,它几乎与编写同步阻塞代码完全相同。当然,这也适用于任何共享状态的问题。
await
中的多线程问题与阻塞多线程I/O中的多线程问题没有太大区别。
Task
s更容易避免,但这只是因为您拥有的工具,而不是因为
Task
s所具有的任何“魔力”

在这方面与goroutines的主要区别在于Go并没有通常意义上的阻塞方法。它们不是阻塞,而是将特定的异步请求排队,并产生响应。当操作系统(以及Go中的任何其他层——我对内部工作没有深入的了解)接收到响应时,它将其发布到goroutine调度程序,而goroutine调度程序又知道“等待”响应的goroutine现在可以恢复执行了;当它实际得到一个插槽时,它将从“阻塞”调用继续,就像它真的被阻塞一样——但实际上,它与C#的
wait
非常相似。没有根本的区别——C#的方法和Go的方法有很多区别,但它们并没有那么大


还要注意的是,这与旧Windows系统上使用的方法基本相同,没有先发制人的多任务——任何“阻塞”方法都只会将线程的执行返回给调度程序。当然,在这些系统上,您只有一个CPU内核,因此无法同时执行多个线程,但原理仍然相同。

goroutines就是我们所说的。它们不是操作系统线程,由go调度程序负责。这就是为什么它们可以有更小的内存占用。

goroutine不是线程,它们是(来自):

…同一地址空间内的独立并发控制线程或goroutine

将其定义为:

它们被称为goroutines,因为现有的术语threads、corroutine、processs等等传达了不准确的含义。goroutine有一个简单的模型:它是一个与同一地址空间中的其他goroutine并发执行的函数。它是轻量级的,只需分配堆栈空间。堆栈开始时很小,所以很便宜,并通过根据需要分配(和释放)堆存储来增长

goroutine没有自己的线程。相反,多个goroutine(可能)被多路复用到相同的OS线程上,因此如果一个goroutine阻塞(例如,等待I/O或阻塞通道操作),其他goroutine将继续运行

可以使用该函数设置同时执行goroutine的实际线程数。从包装文件中引用:

GOMAXPROCS变量限制可以同时执行用户级Go代码的操作系统线程数。代表Go代码在系统调用中可以阻止的线程数量没有限制;这些不计入GOMAXPROCS限制<