ホームページ > バックエンド開発 > Golang > GO:同期が取れていない

GO:同期が取れていない

Linda Hamilton
リリース: 2024-11-30 01:10:11
オリジナル
513 人が閲覧しました

GO:lack of synchronization

var a string
var done bool

func setup() {
    a = "hello, world"
    done = true
}

func doprint() {
    if !done {
        once.Do(setup)
    }
    print(a)
}

func twoprint() {
    go doprint()
    go doprint()
}
ログイン後にコピー

コード分​​析

変数:

  • a と b は int 型のグローバル変数であり、すべてのゴルーチンによって共有されます。

関数:

  • f():
    • a と b に順番に書き込みます (a = 1 および b = 2)。
  • g():
  • b を読み取り、その後に a を出力します。

main() の同時実行:

  • 関数 f() は go f() を使用して別のゴルーチンとして実行されます。
  • 関数 g() はメインの goroutine で直接実行されます。

潜在的な問題:

  • f() を実行するゴルーチンと g() を実行するメインのゴルーチンは同時に実行されます。
  • f() での a と b への書き込みは、g() が a と b の値を読み取って出力する前に完了しない可能性があります。
  • これによりデータ競合が発生し、同期なしで共有メモリ (a および b) 上で同時アクセス (f() への書き込みと g() への読み取り) が発生します。

考えられる結果
同期が欠如しているため、プログラムの出力は非決定的になります。考えられるシナリオは次のとおりです:

ケース 1: f() が a と b を変更する前に g() が実行されます:

  • a と b の初期値は 0 (Go の初期化されていない int のデフォルト) です。
0
0

ログイン後にコピー

または

ケース 2: g() の前に b = 2 が完了したが、a = 1 が完了していない場合、出力は次のようになります:

2
0
ログイン後にコピー

主な所見
データ競合: 同期せずに a と b に同時にアクセスすると、データ競合が発生します。これにより、プログラムの動作が未定義で予測不能になります

コードの修正

  1. sync.WaitGroup の使用: g() が実行される前に f() が完了することを確認する
var a, b int
var wg sync.WaitGroup

func f() {
    a = 1
    b = 2
    wg.Done()
}

func g() {
    print(b)
    print(a)
}

func main() {
    wg.Add(1)
    go f()
    wg.Wait()
    g()
}

ログイン後にコピー
  1. チャネルの使用: f() が完了したときにシグナルを送信します。
var a, b int

func f(done chan bool) {
    a = 1
    b = 2
    done <- true
}

func g() {
    print(b)
    print(a)
}

func main() {
    done := make(chan bool)
    go f(done)
    <-done
    g()
}

ログイン後にコピー

ここで、g() は、f() が Done チャネル経由でシグナルを送信するまで待機します。

以上がGO:同期が取れていないの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート