Kuasai mod konkurensi dan pengkomputeran selari bahasa Go

王林
Lepaskan: 2023-11-30 09:30:33
asal
758 orang telah melayarinya

Kuasai mod konkurensi dan pengkomputeran selari bahasa Go

Dengan perkembangan pesat Internet, permintaan untuk sistem teragih berskala besar semakin tinggi, dan pengaturcaraan serentak dan pengkomputeran selari telah menjadi kemahiran yang mesti dikuasai oleh pembangun Internet. Bahasa Go ialah bahasa yang dilahirkan untuk menyokong konkurensi Ia berfungsi dengan baik dalam pengaturcaraan serentak dan pengkomputeran selari. Artikel ini akan memperkenalkan mod konkurensi dan pengkomputeran selari bagi bahasa Go dan memberikan beberapa kes praktikal untuk membantu pembaca memahami secara mendalam.

1. Mod konkurensi bahasa Go

Mod konkurensi bahasa Go adalah berdasarkan kepada dua komponen asas goroutine dan saluran. Goroutine ialah benang ringan, diuruskan oleh sistem masa jalan bahasa Go. Ia boleh dimulakan melalui kata kunci go, dan goroutine boleh berkomunikasi melalui saluran.

Berikut ialah contoh mudah goroutine dan saluran:

package main

import "fmt"

func printMsg(msg string, ch chan string) {
    ch <- msg
}

func main() {
    ch := make(chan string)
    msgs := []string{"Hello", "Golang", "Parallel"}

    for _, msg := range msgs {
        go printMsg(msg, ch)
    }

    for i := 0; i < len(msgs); i++ {
        fmt.Println(<-ch)
    }
}
Salin selepas log masuk

Kod ini memulakan tiga goroutine melalui gelung for dan masing-masing mengeluarkan tiga rentetan. Fungsi printMsg menulis mesej rentetan ke dalam saluran, dan fungsi utama membaca dari saluran semula.

1.1 Mod Saluran Paip

Dalam bahasa Go, berbilang goroutin boleh disambungkan secara bersiri melalui mod saluran paip untuk membentuk sistem serentak yang lebih kompleks. Pelaksanaan corak saluran paip biasanya melalui komunikasi saluran antara berbilang goroutine, menghantar data dari satu goroutine ke goroutine yang lain, dan memproses dan menukar data dalam setiap goroutine. Berikut ialah contoh mod saluran paip mudah:

package main

import (
    "fmt"
)

func addOne(in <-chan int, out chan<- int) {
    for val := range in {
        out <- val + 1
    }
    close(out)
} 

func printNums(out <-chan int) {
    for val := range out {
        fmt.Println(val)
    }
}

func main() {    
    nums := []int{1, 2, 3}
    in := make(chan int)
    out := make(chan int)

    go addOne(in, out)

    go printNums(out)

    for _, num := range nums {
        in <- num
    }
    close(in)
}
Salin selepas log masuk

Kod mentakrifkan 3 goroutine, iaitu goroutine input, ditambah 1 goroutine pemprosesan dan goroutine keluaran Fungsi addOne menambah 1 pada data dalam saluran input dan menulisnya ke saluran output, printNums Fungsi membaca data daripada saluran keluaran dan mengeluarkannya.

1.2 Corak pemilihan

Pernyataan pilih bahasa Go menyediakan cara yang mudah untuk mengendalikan berbilang saluran, iaitu corak pemilihan (corak pilih). Mod pemilihan membolehkan kami melakukan operasi pemilihan tanpa sekatan dalam berbilang saluran Apabila terdapat mesej yang boleh dibaca atau boleh ditulis dalam berbilang saluran, satu akan dipilih secara automatik untuk operasi.

Berikut ialah contoh mod pemilihan mudah:

package main

import "fmt"

func ping(ch chan<- string) {
    for {
        ch <- "ping"
    }
}

func pong(ch chan<- string) {
    for {
        ch <- "pong"
    }
}

func printer(ch <-chan string) {
    for {
        fmt.Println(<-ch)
    }
}

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)
    ch3 := make(chan string)

    go ping(ch1)
    go pong(ch2)
    go printer(ch3)

    for {
        select {
        case msg := <-ch1:
            ch3 <- msg
        case msg := <-ch2:
            ch3 <- msg
        }
    }
}
Salin selepas log masuk

Dalam kod, fungsi ping dan fungsi pong menghantar mesej "ping" dan "pong" masing-masing ke ch1 dan ch2, dan fungsi pencetak membaca mesej dalam ch3 dan output ia. Dalam fungsi utama, gunakan pernyataan pilih untuk memantau mesej dalam ch1 dan ch2, dan hantar mesej yang diterima ke fungsi pencetak melalui ch3 untuk output.

2. Pengkomputeran selari bahasa Go

Modul pengkomputeran selari terbina dalam bahasa Go termasuk penyegerakan, atom dan konteks, dsb. penyegerakan dan atom terutamanya menggunakan mutex (Mutex) dan operasi atom (operasi atom) untuk mengawal akses data serentak, dan konteks digunakan untuk mengurus maklumat konteks goroutine. Berikut ialah pengenalan ringkas tentang cara menggunakan modul ini:

2.1 Mutex lock

Mutex lock ialah salah satu mekanisme penyegerakan yang paling biasa digunakan untuk melindungi sumber yang dikongsi, dan ia juga merupakan salah satu mekanisme penyegerakan paling asas dalam bahasa Go . Dalam bahasa Go, anda boleh mencipta kunci mutex melalui jenis Mutex dalam pakej penyegerakan. Jenis Mutex menyediakan dua kaedah penting: Kunci dan Buka Kunci. Sebelum mengakses sumber yang dikongsi, anda perlu memanggil kaedah Kunci untuk mendapatkan kunci, dan kemudian memanggil kaedah Buka Kunci untuk melepaskan kunci selepas akses selesai. Berikut ialah contoh kunci mutex mudah:

package main

import (
    "fmt"
    "sync"
)

func addOne(num *int, mutex *sync.Mutex, wg *sync.WaitGroup) {
    mutex.Lock()
    *num += 1
    mutex.Unlock()

    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    var num int

    mutex := &sync.Mutex{}
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go addOne(&num, mutex, &wg)
    }

    wg.Wait()
    fmt.Println(num)
}
Salin selepas log masuk

Dalam kod, fungsi addOne ditakrifkan untuk menambah 1 pada pembolehubah num Kunci mutex perlu diperoleh sebelum menambah 1, dan kunci mutex perlu dilepaskan selepas menambah 1. Gunakan WaitGroup untuk menunggu semua gorout menyelesaikan pelaksanaan dan menghasilkan keputusan akhir.

2.2 Operasi atom

Dalam senario konkurensi tinggi, kunci mutex mungkin mengurangkan prestasi program, jadi bahasa Go menyediakan operasi atom untuk menggantikan kunci mutex. Pakej atom menyediakan beberapa fungsi operasi atom, seperti AddInt64, CompareAndSwapInt64, SwapInt64, dsb. Menggunakan operasi atom memastikan bahawa operasi pada pembolehubah tidak akan diganggu oleh goroutine lain dan pelaksanaan serentak tidak akan terjejas. Berikut ialah contoh operasi atom yang mudah:

package main

import (
    "fmt"
    "sync/atomic"
)

func addOne(num *int64, count *int64, done chan bool) {
    for i := 0; i < 1000; i++ {
        atomic.AddInt64(num, 1)
    }
    atomic.AddInt64(count, 1)
    done <- true
}

func main() {
    var num int64
    var count int64
    done := make(chan bool)

    for i := 0; i < 100; i++ {
        go addOne(&num, &count, done)
    }

    for i := 0; i < 100; i++ {
        <-done
    }

    fmt.Printf("num=%d, count=%d
", num, count)
}
Salin selepas log masuk

Dalam kod, fungsi AddInt64 bagi pakej atom digunakan untuk melaksanakan operasi atom pada pembolehubah num Selepas operasi selesai, utas utama dimaklumkan melalui selesai. Pembolehubah kiraan terkumpul melalui fungsi AddInt64 biasa, dan nilai nombor dan kiraan akhirnya dikeluarkan.

2.3 Pengurusan Konteks

Dalam bahasa Go, selalunya perlu untuk menghantar maklumat konteks antara berbilang goroutin, seperti ID permintaan, tetapan tamat masa, dsb. Pakej konteks menyediakan cara yang mudah untuk mengurus maklumat konteks goroutine. Apabila menggunakan konteks, anda biasanya perlu mencipta konteks induk dalam goroutine utama Apabila memperoleh goroutine, gunakan WithCancel, WithDeadline, WithValue dan fungsi lain untuk mencipta konteks kanak-kanak dan menyampaikan maklumat konteks yang sepadan. Berikut ialah contoh pengurusan konteks mudah:

package main

import (
    "context"
    "fmt"
    "time"
)

func worker(ctx context.Context, id int) {
    for {
        select {
        case <-ctx.Done():
            fmt.Printf("worker %d canceled
", id)
            return
        default:
            fmt.Printf("worker %d is working
", id)
            time.Sleep(1 * time.Second)
        }
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())

    for i := 0; i < 3; i++ {
        go worker(ctx, i)
    }

    time.Sleep(5 * time.Second)

    cancel()
}
Salin selepas log masuk

Dalam kod, gunakan pakej konteks untuk mencipta konteks induk dan cipta konteks kanak-kanak melalui fungsi WithCancel. Dalam fungsi pekerja, gunakan pernyataan pilih untuk mendengar isyarat ctx.Done() Apabila ctx.Done() ditutup, ini bermakna konteks dibatalkan dan fungsi pekerja perlu keluar. Dalam fungsi utama, tutup subkonteks melalui fungsi batal dan tunggu subkonteks dibatalkan. Keputusan yang dijalankan adalah seperti berikut:

worker 0 is working
worker 1 is working
worker 2 is working
worker 2 canceled
worker 1 canceled
worker 0 canceled
Salin selepas log masuk

Apabila konteks induk dibatalkan, semua konteks kanak-kanak akan menerima pemberitahuan dan keluar dari pelaksanaan.

3. Kesimpulan

Artikel ini memperkenalkan secara ringkas mod konkurensi dan pengkomputeran selari bahasa Go, dan memperkenalkan komponen dan modul asas seperti goroutine, saluran, kunci mutex, operasi atom dan konteks. Dengan mempelajari pengetahuan asas ini, kita boleh menguasai pengaturcaraan serentak dan selari bahasa Go dengan lebih baik, dan meletakkan asas untuk membina aplikasi Internet berprestasi tinggi dan berkonkurensi tinggi.

Atas ialah kandungan terperinci Kuasai mod konkurensi dan pengkomputeran selari bahasa Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!