2016-12-25 18 views
0

今日、私の友人は、Goプログラムは複数のCPUコアで拡張できることを教えてくれました。私は、システムタスクスケジューラがゴルーチンについて何も知らないので複数のコアでそれらを実行できないことを知っていることに驚いていました。ゴーラン、プロセスと共有メモリ

私はいくつかの検索を行い、Goプログラムが異なるコア(GOMAXPROCS環境変数によって制御される数)上で実行するために複数のOSタスクを起動できることを発見しました。しかし、私が知る限りでは、プロセスデータを完全にコピーし、異なるプロセスが異なるアドレス空間で実行されます。

それでは、囲碁プログラムでグローバル変数についてはどうですか?彼らは複数のゴルーチンで安全に使えますか?彼らは何とかシステムプロセス間で同期しますか?そして、彼らがどうすればよいのか?私は主にLinuxとFreeBSDの実装に懸念しています。

+2

[ゴルーチンの公式文書](https://golang.org/doc/effective_go.html#goroutines)は参考にしてください。 – chrk

+0

[この記事](https://www.goinggo.net/2014/01/concurrency-goroutines-and-gomaxprocs.html)。 – chrk

+0

@chrkの問題は、公式のドキュメントでも、2番目の記事でランタイムがどうやってシェア変数の同期を提供しているのかが分かりません。公式ドキュメントには、「ゴルーチンには単純なモデルがあります。これは、同じアドレス空間内の他のゴルーチンと同時に実行される関数です」。しかし、異なるプロセスにいる場合、同じアドレス空間に置くことはできません。 – ea7ababe

答えて

4

私はそれを理解しました!それはすべての情報源です。

私は知らなかったLinuxシステムコールがあります。 「クローン」と呼ばれています。これはforkよりも柔軟性があり、子プロセスが親のアドレス空間に居ることを可能にします。ここで

は、スレッドの作成プロセスの簡単な概要です。

まず、src/runtime/proc.gonewmの機能があります。この 関数は、新しいワーキングスレッド (またはコメント内で呼び出されるマシン)を作成します。

// 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つの共有アドレス空間が使用されます。

ふう...私は行くが大好きです。

関連する問題