21

Java は、コードの重要な部分を同期するための非常に便利なイディオムを提供します。

synchronized(someObject) {
    // do something really important all by myself with nobody bothering me
}

または

public synchronized void doSomething() {
    // ...
}

同等のgoは何ですか?

(簡単な検索で次のことがわかります: golang.org/pkg/sync/ - これは (おそらく私が間違っているかもしれませんが) 一般的な使用にはレベルが低すぎるようです。)

(私がこれを気にする理由の例: チャネルを介して複数のリスナーにメッセージを送信する必要があります。チャネルは、何も同期しなくてもデータの適切な導管を提供しますが、チャネルが追加または削除されると、チャネルのリストを変更する必要があります。いつでも発生する可能性があり、同時実行性に対処できる必要があります。)

4

3 に答える 3

20

sync.Mutexsynchronizedは相互排除ロックであり、 Java キーワードと同様の機能を提供できます(ただし、Java のロックはreentrant相互排除を提供します)。

synchronized(someObject) {
    //   
}

と同等です:

var l sync.Mutex

l.Lock()
//
l.Unlock()
于 2013-09-18T19:39:59.317 に答える
13

tarrsalahの答えを拡張します。

オブジェクトに sync.Mutex を追加して、オブジェクトを直接ロックおよびロック解除できます。

type MyObject struct{
    Number int
    sync.Mutex
}

func (m *MyObject)Increment(){
    m.Lock()
    defer m.Unlock()
    m.Number++
}

Defer'd コマンドは関数の最後に実行されます。このようにして、より大きな関数でロックとロック解除の両方が行われることがわかります。

于 2016-01-01T09:44:33.017 に答える
9

ミューテックスを使用する別の解決策は、チャネルを使用してリスナーの変更を伝達することです。

このスタイルの完全な例は次のようになります。興味深いコードは FanOuter にあります。

package main

import (
    "fmt"
    "time"
)

type Message int

type ListenerUpdate struct {
    Add      bool
    Listener chan Message
}

// FanOuter maintains listeners, and forwards messages from msgc
// to each of them. Updates on listc can add or remove a listener.
func FanOuter(msgc chan Message, listc chan ListenerUpdate) {
    lstrs := map[chan Message]struct{}{}
    for {
        select {
        case m := <-msgc:
            for k := range lstrs {
                k <- m
            }
        case lup := <-listc:
            if lup.Add {
                lstrs[lup.Listener] = struct{}{}
            } else {
                delete(lstrs, lup.Listener)
            }
        }
    }
}

func main() {
    msgc := make(chan Message)
    listc := make(chan ListenerUpdate)
    go FanOuter(msgc, listc)
    // Slowly add listeners, then slowly remove them.
    go func() {
        chans := make([]chan Message, 10)
        // Adding listeners.
        for i := range chans {
            chans[i] = make(chan Message)
            // A listener prints its id and any messages received.
            go func(i int, c chan Message) {
                for {
                    m := <-c
                    fmt.Printf("%d received %d\n", i, m)
                }
            }(i, chans[i])
            listc <- ListenerUpdate{true, chans[i]}
            time.Sleep(300 * time.Millisecond)
        }
        // Removing listeners.
        for i := range chans {
            listc <- ListenerUpdate{false, chans[i]}
            time.Sleep(300 * time.Millisecond)
        }
    }()
    // Every second send a message to the fanouter.
    for i := 0; i < 10; i++ {
        fmt.Println("About to send ", i)
        msgc <- Message(i)
        time.Sleep(1 * time.Second)
    }
}
于 2013-09-19T14:11:47.983 に答える