私はそれを理解しました!それはすべての情報源です。
私は知らなかったLinuxシステムコールがあります。 「クローン」と呼ばれています。これはforkよりも柔軟性があり、子プロセスが親のアドレス空間に居ることを可能にします。ここで
は、スレッドの作成プロセスの簡単な概要です。
まず、src/runtime/proc.go
にnewm
の機能があります。この 関数は、新しいワーキングスレッド (またはコメント内で呼び出されるマシン)を作成します。
// Create a new m. It will start off with a call to fn, or else the scheduler.
// fn needs to be static and not a heap allocated closure.
// May run with m.p==nil, so write barriers are not allowed.
//go:nowritebarrier
func newm(fn func(), _p_ *p) {
// ... some code skipped ...
newosproc(mp, unsafe.Pointer(mp.g0.stack.hi))
}
この機能は、OS固有のものであるnewosproc
を呼び出します。 Linuxの場合はsrc/runtime/os_linux.go
にあります。ここ は、そのファイルの関連する部分です:
var (
// ...
cloneFlags = _CLONE_VM | /* share memory */
_CLONE_FS | /* share cwd, etc */
_CLONE_FILES | /* share fd table */
_CLONE_SIGHAND | /* share sig handler table */
_CLONE_THREAD /* revisit - okay for now */
)
// May run with m.p==nil, so write barriers are not allowed.
//go:nowritebarrier
func newosproc(mp *m, stk unsafe.Pointer) {
// ... some code skipped ...
ret := clone(cloneFlags, /* ... other flags ... */)
// ... code skipped
}
そしてclone
機能はアーキテクチャ固有 ファイルで定義されています。 amd64の場合はsrc/runtime/sys_linux_amd64.s
です。 実際のシステムコールです。
したがって、Goプログラムは複数のOSスレッドで実行され、 はCPU間で共有されますが、1つの共有アドレス空間が使用されます。
ふう...私は行くが大好きです。
[ゴルーチンの公式文書](https://golang.org/doc/effective_go.html#goroutines)は参考にしてください。 – chrk
[この記事](https://www.goinggo.net/2014/01/concurrency-goroutines-and-gomaxprocs.html)。 – chrk
@chrkの問題は、公式のドキュメントでも、2番目の記事でランタイムがどうやってシェア変数の同期を提供しているのかが分かりません。公式ドキュメントには、「ゴルーチンには単純なモデルがあります。これは、同じアドレス空間内の他のゴルーチンと同時に実行される関数です」。しかし、異なるプロセスにいる場合、同じアドレス空間に置くことはできません。 – ea7ababe