Rumah > pembangunan bahagian belakang > Golang > Aplikasi gabungan primitif penyegerakan dan strategi pengoptimuman prestasi di Golang

Aplikasi gabungan primitif penyegerakan dan strategi pengoptimuman prestasi di Golang

WBOY
Lepaskan: 2023-09-27 12:16:41
asal
1447 orang telah melayarinya

Aplikasi gabungan primitif penyegerakan dan strategi pengoptimuman prestasi di Golang

Golang ialah bahasa pengaturcaraan dengan kecekapan pelaksanaan yang tinggi, dan ciri pengaturcaraan serentaknya digunakan secara meluas dalam pelbagai senario permintaan. Dalam perpustakaan standard Golang, banyak primitif penyegerakan disediakan untuk melaksanakan kawalan konkurensi, seperti mutex, saluran, dsb. Pada masa yang sama, kami juga boleh menggunakan beberapa strategi pengoptimuman prestasi untuk meningkatkan lagi kecekapan menjalankan program. Artikel ini akan memperkenalkan cara menggabungkan primitif penyegerakan dan strategi pengoptimuman prestasi di Golang, dan menyediakan contoh kod khusus.

1. Pengenalan dan senario aplikasi primitif penyegerakan
Primitif penyegerakan direka untuk menyelaraskan urutan pelaksanaan dan akses data antara berbilang goroutin serentak. Di Golang, primitif penyegerakan yang paling biasa digunakan ialah mutex, cond dan waitgroup.

1.1 mutex
mutex ialah kunci mutex yang melindungi kod dalam bahagian kritikal untuk memastikan berbilang goroutine tidak mengakses sumber kongsi pada masa yang sama. Mutex menggunakan dua kaedah, Lock() dan Unlock(), yang pertama digunakan untuk memperoleh kunci, dan yang terakhir digunakan untuk melepaskan kunci.

Secara amnya, apabila berbilang goroutine perlu membaca dan menulis sumber kongsi yang sama, kami boleh menggunakan mutex untuk memastikan akses selamat kepada sumber tersebut. Berikut ialah kod sampel menggunakan mutex:

package main

import (
    "fmt"
    "sync"
)

var (
    count int
    mux   sync.Mutex
)

func increment() {
    mux.Lock()
    count++
    mux.Unlock()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            increment()
        }()
    }
    wg.Wait()
    fmt.Println("Count:", count)
}
Salin selepas log masuk

Dalam kod di atas, kami mencipta kiraan pembolehubah global dan berbilang goroutin menambah kiraan dengan memanggil fungsi kenaikan. Untuk memastikan akses selamat untuk mengira, kami menggunakan mutex untuk kawalan mutex.

1.2 cond
cond ialah pembolehubah keadaan yang boleh menghantar isyarat antara goroutine. Apabila goroutine menunggu syarat tertentu untuk dipenuhi, ia boleh menggantung dirinya melalui kaedah Tunggu cond, dan kemudian meneruskan pelaksanaan selepas syarat dipenuhi.

Senario di mana cond digunakan secara amnya adalah model pengeluar-pengguna Kod contoh khusus adalah seperti berikut:

package main

import (
    "fmt"
    "sync"
)

var (
    count     int
    maxCount  = 10
    condition = sync.NewCond(&sync.Mutex{})
)

func produce() {
    condition.L.Lock()
    for count > maxCount {
        condition.Wait()
    }
    count++
    fmt.Println("Produce:", count)
    condition.L.Unlock()
    condition.Signal()
}

func consume() {
    condition.L.Lock()
    for count <= 0 {
        condition.Wait()
    }
    count--
    fmt.Println("Consume:", count)
    condition.L.Unlock()
    condition.Signal()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(2)
        go func() {
            defer wg.Done()
            produce()
        }()

        go func() {
            defer wg.Done()
            consume()
        }()
    }
    wg.Wait()
}
Salin selepas log masuk

Dalam kod di atas, kami melaksanakan model pengeluar-pengguna yang mudah melalui cond. Apabila kiraan melebihi maxCount, pengeluar menggantung dirinya dengan memanggil kaedah Tunggu cond, dan kemudian membangunkan goroutine menunggu lain dengan memanggil kaedah Isyarat cond selepas pengguna menggunakan.

1.3 waitgroup
waitgroup ialah kaunter yang boleh menunggu sekumpulan goroutine dilaksanakan sebelum meneruskan. waitgroup menyediakan tiga kaedah Add(), Done() dan Wait() Dua yang pertama digunakan untuk menambah dan mengurangkan pembilang, dan yang terakhir digunakan untuk menunggu pembilang kembali kepada sifar.

Senario penggunaan kumpulan tunggu biasanya apabila goroutin utama menunggu goroutin serentak lain selesai sebelum meneruskan ke langkah seterusnya. Berikut ialah kod sampel kumpulan tunggu:

package main

import (
    "fmt"
    "sync"
)

var (
    count int
    wg    sync.WaitGroup
)

func increment() {
    defer wg.Done()
    count++
}

func main() {
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go increment()
    }
    wg.Wait()
    fmt.Println("Count:", count)
}
Salin selepas log masuk

Dalam kod di atas, kami menggunakan kumpulan tunggu untuk memastikan semua goroutin dilaksanakan sebelum mengeluarkan nilai kiraan.

2. Pengenalan kepada strategi pengoptimuman prestasi dan senario aplikasi
Di Golang, terdapat beberapa strategi pengoptimuman prestasi yang boleh membantu kami meningkatkan kecekapan menjalankan program. Berikut memperkenalkan beberapa strategi pengoptimuman yang biasa digunakan dan memberikan contoh kod khusus. . Oleh itu, menggunakan kumpulan goroutine untuk menggunakan semula goroutine yang telah dibuat ialah strategi pengoptimuman prestasi.

Berikut ialah contoh kod yang menggunakan kumpulan goroutine untuk memproses tugas secara serentak:

package main

import (
    "fmt"
    "runtime"
    "sync"
)

type Task struct {
    ID int
}

var tasksCh chan Task

func worker(wg *sync.WaitGroup) {
    defer wg.Done()
    for task := range tasksCh {
        fmt.Println("Processing task:", task.ID)
    }
}

func main() {
    numWorkers := runtime.NumCPU()
    runtime.GOMAXPROCS(numWorkers)
    tasksCh = make(chan Task, numWorkers)
    var wg sync.WaitGroup
    for i := 0; i < numWorkers; i++ {
        wg.Add(1)
        go worker(&wg)
    }

    for i := 0; i < 10; i++ {
        tasksCh <- Task{ID: i}
    }

    close(tasksCh)
    wg.Wait()
}
Salin selepas log masuk

Dalam kod di atas, kami memperoleh bilangan teras CPU mesin semasa melalui fungsi runtime.NumCPU() dan tetapkan GOMAXPROCS melalui fungsi runtime.GOMAXPROCS() Nilai ialah bilangan teras CPU untuk meningkatkan kecekapan serentak. Pada masa yang sama, kami menggunakan goroutine dalam kumpulan goroutine untuk memproses tugas secara serentak untuk mengelakkan penciptaan dan pemusnahan yang kerap.

2.2 Struktur data tanpa kunci

Kunci Mutex akan menyebabkan masalah persaingan kunci dalam senario konkurensi tinggi, mengakibatkan kemerosotan prestasi. Untuk meningkatkan prestasi serentak program, kami boleh menggunakan struktur data tanpa kunci untuk mengelakkan pertikaian kunci.

Berikut ialah kod sampel yang menggunakan operasi atom dalam pakej penyegerakan/atom untuk melaksanakan pembilang bebas kunci:

package main

import (
    "fmt"
    "sync/atomic"
)

var count int32

func increment() {
    atomic.AddInt32(&count, 1)
}

func main() {
    for i := 0; i < 1000; i++ {
        go increment()
    }
    fmt.Println("Count:", atomic.LoadInt32(&count))
}
Salin selepas log masuk

Dalam kod di atas, kami menggunakan fungsi AddInt32 dan LoadInt32 dalam pakej atom untuk melaksanakan operasi atom pada kaunter, mencapai Tiada kesan pengiraan kunci.

3. Aplikasi gabungan primitif penyegerakan dan strategi pengoptimuman prestasi

Dalam pembangunan sebenar, kami sering menghadapi senario yang memerlukan kedua-dua memastikan keselamatan serentak dan meningkatkan kecekapan operasi program. Berikut ialah contoh kod yang menggabungkan mutex dan struktur data tanpa kunci:

package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

var (
    count int32
    mux   sync.Mutex
)

func increment() {
    atomic.AddInt32(&count, 1)
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            mux.Lock()
            increment()
            mux.Unlock()
        }()
    }
    wg.Wait()
    fmt.Println("Count:", atomic.LoadInt32(&count))
}
Salin selepas log masuk

Dalam kod di atas, kami menggunakan mutex untuk memastikan akses selamat untuk mengira dan menggunakan operasi atom dalam pakej atom untuk meningkatkan kiraan. Dengan menggabungkan mutex dan struktur data tanpa kunci, kami bukan sahaja memastikan keselamatan serentak, tetapi juga meningkatkan kecekapan menjalankan program.

Melalui kod contoh di atas, kita dapat melihat bahawa gabungan primitif penyegerakan dan strategi pengoptimuman prestasi di Golang boleh meningkatkan prestasi program dan kecekapan dalam senario konkurensi tinggi. Sudah tentu, kaedah aplikasi khusus perlu dipilih berdasarkan keperluan perniagaan khusus dan kesesakan prestasi. Ringkasnya, pemilihan munasabah dan penggunaan primitif penyegerakan dan strategi pengoptimuman prestasi adalah kunci untuk membina program serentak yang cekap.

Atas ialah kandungan terperinci Aplikasi gabungan primitif penyegerakan dan strategi pengoptimuman prestasi di Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

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