2016-09-09 3 views
-1

私はgolangでマルチスレッドを実装しようとしていました。私はgoルーチンを実装することができますが、期待どおりに動作していません。以下、私が用意したサンプルプログラム、goloutineまたはmultithreadingがgolangで動作しない

func test(s string, fo *os.File) { 
    var s1 [105]int 
    count :=0 
    for x :=1000; x<1101;x++ { 
    s1[count] = x; 
     count++ 
    } 

    //fmt.Println(s1[0]) 
    for i := range s1 { 
     runtime.Gosched() 
     sd := s + strconv.Itoa(i) 
     var fileMutex sync.Mutex 
     fileMutex.Lock() 
     fmt.Fprintf(fo,sd) 
     defer fileMutex.Unlock() 
    } 
} 

func main() { 
    fo,err :=os.Create("D:/Output.txt") 
    if err != nil { 
     panic(err) 
    } 
    for i := 0; i < 4; i++ { 
     go test("bye",fo) 

    } 



} 

OUTPUTある - good0bye0bye0bye0bye0good1bye1bye1bye1bye1good2bye2bye2bye2bye2 ....など 上記のプログラムは、ファイルに「BYE」ファイルを作成して書き込み、「こんにちは」となります。

私の問題は5スレッドを作成しようとしていて、別のスレッドで異なる値の値を処理したかったのです。上記の例が表示される場合は、「bye」を4回印刷しています。

iは、など....

任意のアイデアどのように私はこれを達成することができます.... 5スレッド、

good0bye0good1bye1good2bye2を使用して、以下のような出力をしたいですか?

+2

あなたの主な機能を妨げるものは何もありません。すべての出力が表示される前に、プログラムが終了します。 – JimB

+0

@JimBご返信ありがとうございます。ファイルに書き込んで作業しています。 – user2768132

+0

メインでブロッキングがないこと(最初に修正する必要があります)のほかに、mutexはgoroutine間で共有されないため、何もロックしていませんし、ループごとに初期化された別個のmutexもあります。 。あなたは戻っていないときにロックを解除するためにdeferを呼び出します。よく動作するプログラムで 'runtime.GoSched'を呼び出す必要はありません。 – JimB

答えて

3

まず、他のすべてのゴルーチンが戻るまでメイン関数をブロックする必要があります。あなたのプログラムのmutexesは何もをブロックしていないし、各ループで再初期化されているので、自分のゴルーチン内でブロックさえしない。関数から戻ってこない場合は、ロック解除を延期することはできません。ループの各反復で明示的にロックを解除する必要があります。配列の値は使用していません(代わりにスライスを使用する必要があります)ので、その値を完全に削除することができます。うまく動作するプログラムにruntime.GoSchedは必要なく、ここでは何もしません。

完了まで実行されます同等のプログラムは次のようになります。

var wg sync.WaitGroup 

var fileMutex sync.Mutex 

func test(s string, fo *os.File) { 
    defer wg.Done() 
    for i := 0; i < 105; i++ { 
     fileMutex.Lock() 
     fmt.Fprintf(fo, "%s%d", s, i) 
     fileMutex.Unlock() 
    } 
} 

func main() { 
    fo, err := os.Create("D:/output.txt") 
    if err != nil { 
     log.Fatal(err) 
    } 
    for i := 0; i < 4; i++ { 
     wg.Add(1) 
     go test("bye", fo) 

    } 
    wg.Wait() 
} 

は最後にかかわらず、複数のゴルーチンから単一のファイルにシリアル値を試してみて、書き込みする理由はありません、それはそうするために非効率的です。値全体をファイル全体に並べ替えるには、とにかく単一のゴルーチンを使用する必要があります。

+0

ご協力いただきありがとうございます。私はそれを実装しようとします。私はそれが5スレッドを作成し、各スレッドが異なる値を印刷していることを期待しています。ところで、これはGoLangでマルチスレッドを実装する正しい方法ですか、そうすることができる他の簡単な方法がありますか? – user2768132

+0

GoはOSスレッドを公開しないので、同時実行にはgoroutinesを使用します。 – JimB

+0

あなたの意見がありました。しかし、私はまだここで並列性を達成することができません。上記の例では、データを1つずつロックして処理しています。私はすべてのスレッドを並列に処理したい。どのように私はそうすることができますか?たとえば、コレクションがあり、サービスやデータベースからデータを取得したい場合、どうすればよいのですか? – user2768132

関連する問題