Perkongsian petua praktikal untuk pengaturcaraan serentak di Golang: memberikan permainan penuh kepada kelebihan Goroutines

PHPz
Lepaskan: 2023-07-19 12:43:48
asal
768 orang telah melayarinya

Perkongsian petua praktikal untuk pengaturcaraan serentak di Golang: Berikan permainan sepenuhnya kepada kelebihan Goroutines

Dalam bahasa Go, Goroutines ialah pelaksanaan utas yang ringan, yang menjadikan pengaturcaraan serentak sangat mudah dan cekap. Dengan memberikan permainan sepenuhnya kepada kelebihan Goroutines, kami boleh menggunakan pemproses berbilang teras dengan lebih baik dan meningkatkan prestasi dan daya pemprosesan program. Artikel ini akan berkongsi beberapa petua praktikal untuk membantu anda menggunakan Goroutines dengan lebih baik untuk pengaturcaraan serentak.

1. Penyelesaian kepada masalah serentak

Dalam pengaturcaraan serentak, masalah yang paling biasa ialah akses serentak kepada sumber yang dikongsi. Untuk menyelesaikan masalah ini, kita boleh menggunakan mutex atau saluran untuk melindungi akses kepada sumber yang dikongsi.

  1. Mutex lock

Mutex lock boleh memastikan bahawa hanya satu Goroutine boleh mengakses sumber kongsi pada masa yang sama dan Goroutine lain perlu menunggu sehingga kunci dilepaskan sebelum mereka boleh mengaksesnya. Berikut ialah contoh kod mudah:

package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mutex   sync.Mutex
    wg      sync.WaitGroup
)

func main() {
    wg.Add(2)
    go increment(1)
    go increment(2)
    wg.Wait()
    fmt.Println("counter:", counter)
}

func increment(id int) {
    defer wg.Done()

    for i := 0; i < 100000; i++ {
        mutex.Lock()
        counter++
        mutex.Unlock()
    }
}
Salin selepas log masuk

Dalam kod di atas, kami menggunakan sync.Mutex untuk mencipta kunci mutex. Dalam fungsi increment, sebelum setiap pengubahsuaian kepada counter sumber yang dikongsi, kami mula-mula memanggil kaedah Lock untuk mengunci mutex, dan kemudian memanggil < kod>Buka kuncikaedah untuk membuka kunci. Ini memastikan bahawa hanya satu Goroutine yang mengubah suai kaunter pada masa yang sama. sync.Mutex来创建了一个互斥锁。在increment函数中,每次对共享资源counter进行修改之前,我们先调用Lock方法锁定互斥锁,然后再调用Unlock方法解锁。这样可以保证同时只有一个Goroutine在修改counter

  1. 通道

通道是一种可以用于在Goroutines之间进行通信的数据结构,它可以实现同步和传递数据。通过通道,我们可以安全地共享资源的访问,避免竞态条件。

下面是一个使用通道的示例代码:

package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    wg      sync.WaitGroup
)

func main() {
    ch := make(chan int)
    wg.Add(2)
    go increment(1, ch)
    go increment(2, ch)
    wg.Wait()
    close(ch)
    
    for count := range ch {
        counter += count
    }
    
    fmt.Println("counter:", counter)
}

func increment(id int, ch chan int) {
    defer wg.Done()

    for i := 0; i < 100000; i++ {
        ch <- 1
    }
}
Salin selepas log masuk

在上面的代码中,我们创建了一个有缓冲的通道ch,通过通道传递整数值1。在increment函数中,我们在每次迭代中,将一个1发送到通道ch中。在main函数中,我们使用range来从通道中接收整数值,然后累加到counter中。

二、避免Goroutine泄漏

在并发编程中,Goroutine泄漏是一种常见的问题。如果Goroutine创建后没有得到正确地关闭,会导致资源的浪费和性能的下降。

为了避免Goroutine泄漏,我们可以使用context包来进行协程控制和取消。下面是示例代码:

package main

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

var wg sync.WaitGroup

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

    wg.Add(1)
    go worker(ctx)

    time.Sleep(3 * time.Second)
    cancel()

    wg.Wait()
    fmt.Println("main function exit")
}

func worker(ctx context.Context) {
    defer wg.Done()

    for {
        select {
        case <-ctx.Done():
            fmt.Println("worker cancelled")
            return
        default:
            fmt.Println("worker is running")
        }

        time.Sleep(1 * time.Second)
    }
}
Salin selepas log masuk

在上面的代码中,我们使用context.Backgroundcontext.WithCancel创建了一个带有取消功能的上下文。在main函数中,我们启动了一个Goroutine来执行worker函数,并传递了上下文。在worker函数中,我们通过不断监听上下文的取消信号来判断是否需要退出。一旦收到取消信号,我们就关闭Goroutine,并输出相应的日志。

通过使用context包,我们可以更好地控制Goroutine的生命周期和资源的释放,避免了Goroutine泄漏。

三、并行执行任务

在实际的应用中,我们经常需要并行执行多个任务,然后等待所有任务完成后再进行下一步操作。这时,我们可以使用sync.WaitGroupchannel来实现。

下面是一个并行执行任务的示例代码:

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {
    tasks := make(chan int, 10)
    wg.Add(3)

    go worker(1, tasks)
    go worker(2, tasks)
    go worker(3, tasks)

    for i := 0; i < 10; i++ {
        tasks <- i
    }

    close(tasks)
    wg.Wait()
    fmt.Println("all tasks done")
}

func worker(id int, tasks chan int) {
    defer wg.Done()

    for task := range tasks {
        fmt.Printf("worker %d: processing task %d
", id, task)
    }
}
Salin selepas log masuk

在上面的代码中,我们创建了一个缓冲为10的通道tasks,然后启动了3个Goroutine来执行worker函数。在main函数中,我们通过循环将10个任务发送到通道中,然后关闭通道。在worker函数中,我们从通道中取出任务,并输出相应的日志。

通过并行执行任务,我们可以充分利用多核处理器,加快程序的执行速度。

总结

通过充分发挥Goroutines的优势,我们可以更好地进行并发编程。在解决共享资源并发访问问题时,我们可以使用互斥锁或通道来保护共享资源的访问。同时,我们也需要注意避免Goroutine泄漏,合理控制Goroutine的生命周期和资源的释放。在需要并行执行任务时,我们可以使用sync.WaitGroupchannel

    Saluran

    🎜Saluran ialah struktur data yang boleh digunakan untuk berkomunikasi antara Goroutines, yang boleh mencapai penyegerakan dan pemindahan data. Melalui saluran, kami boleh berkongsi akses kepada sumber dengan selamat dan mengelakkan keadaan perlumbaan. 🎜🎜Berikut ialah contoh kod menggunakan saluran: 🎜rrreee🎜Dalam kod di atas, kami mencipta saluran penimbal ch dan menghantar nilai integer 1 melalui saluran. Dalam fungsi kenaikan, kami menghantar 1 ke saluran ch pada setiap lelaran. Dalam fungsi utama, kami menggunakan julat untuk menerima nilai integer daripada saluran dan kemudian mengumpulnya ke dalam counter. 🎜🎜2. Elakkan kebocoran Goroutine🎜🎜Dalam pengaturcaraan serentak, kebocoran Goroutine adalah masalah biasa. Jika Goroutine tidak ditutup dengan betul selepas penciptaan, ia akan menyebabkan pembaziran sumber dan kemerosotan prestasi. 🎜🎜Untuk mengelakkan kebocoran Goroutine, kami boleh menggunakan pakej konteks untuk kawalan dan pembatalan coroutine. Berikut ialah kod contoh: 🎜rrreee🎜Dalam kod di atas, kami telah mencipta konteks dengan fungsi pembatalan menggunakan context.Latar Belakang dan context.WithCancel. Dalam fungsi main, kami memulakan Goroutine untuk melaksanakan fungsi worker dan lulus konteks. Dalam fungsi worker, kami sentiasa memantau isyarat pembatalan konteks untuk menentukan sama ada kami perlu keluar. Setelah isyarat pembatalan diterima, kami menutup Goroutine dan mengeluarkan log yang sepadan. 🎜🎜Dengan menggunakan pakej konteks, kami boleh mengawal kitaran hayat Goroutine dan keluaran sumber dengan lebih baik, mengelakkan kebocoran Goroutine. 🎜🎜3. Laksanakan tugasan secara selari🎜🎜Dalam aplikasi sebenar, kita selalunya perlu melaksanakan berbilang tugasan secara selari, dan kemudian tunggu semua tugasan selesai sebelum meneruskan ke langkah seterusnya. Pada masa ini, kita boleh menggunakan sync.WaitGroup dan channel untuk mencapainya. 🎜🎜Berikut ialah contoh kod untuk melaksanakan tugas secara selari: 🎜rrreee🎜Dalam kod di atas, kami mencipta saluran tugas dengan penimbal 10, dan kemudian memulakan 3 Goroutines untuk melaksanakan pekerjafungsi. Dalam fungsi utama, kami menghantar 10 tugasan ke dalam saluran melalui gelung dan kemudian menutup saluran. Dalam fungsi worker, kami mengeluarkan tugasan daripada saluran dan mengeluarkan log yang sepadan. 🎜🎜Dengan melaksanakan tugas secara selari, kami boleh menggunakan sepenuhnya pemproses berbilang teras dan mempercepatkan pelaksanaan program. 🎜🎜Ringkasan🎜🎜Dengan memberikan permainan sepenuhnya kepada kelebihan Goroutines, kami boleh melaksanakan pengaturcaraan serentak dengan lebih baik. Apabila menyelesaikan masalah akses serentak kepada sumber yang dikongsi, kita boleh menggunakan mutex atau saluran untuk melindungi akses kepada sumber yang dikongsi. Pada masa yang sama, kita juga perlu memberi perhatian untuk mengelakkan kebocoran Goroutine dan mengawal kitaran hayat Goroutine dan pelepasan sumber secara munasabah. Apabila kita perlu melaksanakan tugas secara selari, kita boleh menggunakan sync.WaitGroup dan channel untuk mencapainya. 🎜🎜Dengan menggunakan teknik ini dengan betul, kami boleh meningkatkan prestasi dan kelancaran program sambil memastikan ketepatan dan kestabilan program. Saya harap artikel ini akan membantu anda apabila menggunakan Goroutines untuk pengaturcaraan serentak. 🎜

Atas ialah kandungan terperinci Perkongsian petua praktikal untuk pengaturcaraan serentak di Golang: memberikan permainan penuh kepada kelebihan Goroutines. 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!