2016-10-19 3 views
0

以下は、安全にデータにアクセスするためにミューテックスロックを使用する方法の例です。私の質問は、私はどのようにミューテックスのロックとunlock'sを使用する代わりにCSP(通信の順次プロセス)の使用で同じことをやって行くだろうか?チャネルを使用して安全にゴランのデータを同期する方法

type Stack struct { 
    top *Element 
    size int 
    sync.Mutex 
} 

func (ss *Stack) Len() int { 
    ss.Lock() 
    size := ss.size 
    ss.Unlock() 
    return size 

} 

func (ss *Stack) Push(value interface{}) { 
    ss.Lock() 
    ss.top = &Element{value, ss.top} 
    ss.size++ 
    ss.Unlock() 
} 

func (ss *SafeStack) Pop() (value interface{}) { 
    ss.Lock() 
    size := ss.size 
    ss.Unlock() 
    if size > 0 { 
    ss.Lock() 
    value, ss.top = ss.top.value, ss.top.next 
    ss.size-- 
    ss.Unlock() 
    return 
    } 

    return nil 
} 
+0

これは宿題に関する質問ですか?あなたのコードは、 'Element'の定義を含めて、その一部が欠落しているようです。 –

+2

なぜですか?この場合、ミューテックスは正しいプリミティブですか? (また、はるかにクリーンでエラーを起こしにくい 'defer'を使います。 – JimB

+1

チャネルパラダイムの目的は、mutexを取り除くことです。チャンネルを使用すると、チャンネルを使わずに同期することができます。しかし、あなたには、ロックコードだけでなく、実際のコードが必要です。通常、チャネルを効果的に使用するには、その周りにプログラムアーキテクチャを設計する必要があります。それらを効果的に使用するために、いくつかの行を変更することはできません。 – sinned

答えて

1

あなたが実際に実装チャンネルを行く方法を見ていた場合は、基本的に値を通過するまで実行をブロックするために扱ういくつかの追加のスレッドを持つ配列の周りにミューテックスを参照してくださいね。チャンネルの仕事は、ある場所から別の場所にデータを簡単に移動することです。そこであなたは、ロックやアンロックを持っているあなたは、この例のようなものを持っていると思います。ここで

func example() { 
    resChan := make(int chan) 
    go func(){ 
     resChan <- 1 
    }() 
    go func(){ 
     res := <-resChan 
    } 
} 

ので例では、第1ゴルーチンは、第二ゴルーチンがチャンネルから読み取るまで値を送信した後にブロックされています。

Goでmutexを実行するには、sync.WaitGroupを使用します。これは、値の設定時にグループに1を追加し、それをグループから解放し、2番目のゴルーチンがロックしてロックを解除します。

あなたの例の奇妙さは1つのゴルーチンではありません。したがって、すべてが単一のメインゴルーチンで起こります。ロックはより伝統的に使用されています(cスレッドのように)。あなたが持っている例は、ゴーランの諺のように反パターンと見なされます。「メモリを共有して通信しないで、通信することによってメモリを共有してください」と言います。

関連する問題