Rumah >pembangunan bahagian belakang >Golang >Mengapa Goroutine Saya Menambah Pembolehubah Menghasilkan Keputusan Yang Tidak Dijangka?

Mengapa Goroutine Saya Menambah Pembolehubah Menghasilkan Keputusan Yang Tidak Dijangka?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-10-29 20:38:29715semak imbas

Why Does My Goroutine Incrementing a Variable Produce Unexpected Results?

Adakah Ini Hasil Pengoptimuman Pengkompil?

Dalam coretan kod ini, goroutine dilancarkan dan berulang kali menambah pembolehubah i:

<code class="go">package main

import "time"

func main() {
    i := 1
    go func() {
        for {
            i++
        }
    }()
    <-time.After(1 * time.Second)
    println(i)
}</code>

Walau bagaimanapun, output sentiasa 1. Tingkah laku ini boleh dikaitkan dengan model memori Go dan pelaksanaan khusus kod ini.

Model Memori Go

Model memori Go mentakrifkan syarat di mana bacaan pembolehubah dalam satu goroutine boleh dijamin untuk memerhatikan nilai yang dihasilkan dengan menulis kepada pembolehubah yang sama dalam goroutine yang berbeza. Ia menekankan kepentingan penyegerakan untuk akses serentak kepada data yang dikongsi.

Mengabaikan Penyegerakan

Dalam kod yang diberikan:

  • Penugasan kepada i (iaitu, i ) tidak diikuti oleh sebarang peristiwa penyegerakan, menunjukkan bahawa perubahan mungkin tidak dapat dilihat dengan serta-merta kepada gorouti lain.
  • Pengkompil boleh mengoptimumkan pengoptimuman gelung ini dengan memudahkannya kepada no-op.

Pengoptimuman oleh Pengkompil

Pengkompil yang agresif mungkin memadamkan pernyataan i, dengan berkesan mengurangkan goroutine kepada:

<code class="go">for {}</code>

Contoh dengan Penyegerakan

Untuk menunjukkan bahawa isu itu berpunca daripada kekurangan penyegerakan, pertimbangkan kod berikut:

<code class="go">package main

import (
    "sync"
    "time"
)

func main() {
    mx := new(sync.Mutex)
    i := 1
    go func() {
        for {
            mx.Lock()
            i++
            mx.Unlock()
        }
    }()
    <-time.After(1 * time.Second)
    mx.Lock()
    println(i)
    mx.Unlock()
}</code>

Dalam kes ini, output bukan lagi 1, tetapi jumlah yang besar, seperti yang dijangkakan. Penyegerakan.Mutex menyediakan penyegerakan dan memastikan kedua-dua goroutine mengakses i secara terkawal, membenarkan goroutine menambah i dan membuat perubahan kelihatan kepada rutin utama.

Atas ialah kandungan terperinci Mengapa Goroutine Saya Menambah Pembolehubah Menghasilkan Keputusan Yang Tidak Dijangka?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn