2016-09-16 9 views
4

私はポインタレシーバを持つメソッドを持っていますが、このメソッドを使ってこのポインタレシーバをゴルーチンの内部で使用するのが安全かどうか疑問に思っていましたか?または、このポインタ受信機をパラメータとして渡すべきですか?例えばゴルーチンのポインタレシーバの使用

func (m *dummyStruct) doSomething { 
    /* do a bunch of stuff */ 
    go func() { 
     m.a = x 
     m.doSomethingElse() 
    }() 
    return y 
} 

私はあなたがの状態を変更する場合、それは

+0

'dummyStruct'もスレッドセーフである必要があります。モバイル上の – squiguy

答えて

4

非常に必要であるならば、私はゴルーチンにパラメータとしてメートルを渡すことで、間違って行くことはできませんが、私は思っていたことを知っていますmの場合は、ミューテックスロックと慎重なロックパターンが必要です。

これ以外にも、ほとんどの状況でスレッド境界を越えたコンテキスト切り替えが増加します。

私たちが行くのイディオムを持っている理由はここにある:

は、メモリを共有することで通信しないでください。代わりに 、通信によってメモリを共有してください。

https://blog.golang.org/share-memory-by-communicating

0

は私が投稿eduncan911 @リンクを見たが、それを適用しようとしたことがありませんでした。うまくいけば、この例は、役立ちます:

package main 

import (
    "fmt" 
    "time" 
) 

type dummyStruct struct { 
    a int 
} 

func (m *dummyStruct) doSomethingElse() { 
    fmt.Println(m.a) 
} 

func doSomething(c chan int) { 
    for i := 0; i < 5; i++ { 
     go func() { 
      x := time.Now().Unix() 
      c <- int(x) 
     }() 
     time.Sleep(time.Second) 
    } 
} 

func main() { 
    outputs := make(chan int) 
    m := &dummyStruct{} 
    doSomething(outputs) 
    for { 
     //block until we can read from channel: 
     x := <-outputs 
     m.a = x 
     m.doSomethingElse() 
    } 
} 

//Output: 
go run main.go 
1474052448 
1474052449 
1474052450 
1474052451 
1474052452 
fatal error: all goroutines are asleep - deadlock! 
+0

は、stackoverflowでコードを書くための最善の方法ではありません。 ;) – eduncan911

0

私はポインタが、それはパフォーマンスが低下しますと、ゴルーチンとの間でデータを共有するための正しい方法ではないと思います。最善の選択肢はチャンネルです。

+0

これは本当です。なぜなら、変更可能なデータを共有すると、競合状態によって簡単に問題につながるからです。 –

関連する問題