Maison > développement back-end > Golang > le corps du texte

Un blocage se produit lors de l'implémentation récursive/parallèle du tri par fusion dans Golang

WBOY
Libérer: 2024-02-10 13:15:08
avant
436 Les gens l'ont consulté

golang 中合并排序的递归/并行实现中出现死锁

L'éditeur PHP Xigua a découvert que lors de l'utilisation de la récursion ou de l'implémentation parallèle du tri par fusion dans Golang, des problèmes de blocage peuvent survenir. Le tri par fusion est un algorithme de tri couramment utilisé qui peut efficacement diviser un grand tableau en plusieurs petits tableaux pour le tri, puis les fusionner. Cependant, dans la programmation simultanée dans Golang, si vous ne faites pas attention au contrôle de la synchronisation entre les goroutines, un blocage peut survenir. Cet article explorera ce problème en détail et proposera des solutions.

Contenu de la question

J'essaie d'en savoir plus sur la concurrence dans Golang, j'essaie donc d'améliorer l'algorithme MergeSort pour effectuer un tri simultané.

Mon idée est de créer une goroutine à chaque fois que je divise le tableau en deux, donc mon code est le suivant :

func mergeSort(arr []int) []int {
    if len(arr) <= 1 {
        return arr
    }

    mid := len(arr) / 2
    left := arr[:mid]
    right := arr[mid:]

    orderedLeft := make(chan []int)
    orderedRight := make(chan []int)

    var wg sync.WaitGroup

    wg.Add(2)
    go func() {
        defer wg.Done()

        left = mergeSort(left)
        orderedLeft <- left
    }()

    go func() {
        defer wg.Done()
        right = mergeSort(right)
        orderedRight <- right
    }()

    wg.Wait()

    close(orderedLeft)
    close(orderedRight)

    left = <-orderedLeft
    fmt.Println(left)
    right = <-orderedRight
    fmt.Println(right)

    return merge(left, right)
}
Copier après la connexion

Mais j'ai eu une erreur fatale :

fatal error: all goroutines are asleep - deadlock!
Copier après la connexion

Qu'est-ce que j'ai fait de mal ?

Workaround

peut être un peu déroutante car vous mélangez deux modes de concurrence. J'y serai dans un instant.

Lorsque vous utilisez un canal sans tampon, le Goroutine émetteur se bloquera jusqu'à ce que le Goroutine récepteur soit prêt à recevoir la valeur. Dans ce cas, la Goroutine principale attend que deux Goroutines l'utilisent wg.Wait() 完成,而两个 Goroutine 正在尝试将其结果发送到通道 orderedLeftorderedRight. Cependant, comme la goroutine principale ne reçoit pas activement ces valeurs du canal, la goroutine est bloquée et ne peut pas continuer jusqu'à son achèvement.

Vous pouvez facilement résoudre ce problème en mettant en mémoire tampon le canal : orderedRight := make(chan []int, 1).

Cependant, vous pouvez utiliser des canaux ou des waitGroups au lieu de les mélanger, ce qui n'est pas nécessaire dans ce cas :

func mergeSort(arr []int) []int {
    if len(arr) <= 1 {
        return arr
    }

    mid := len(arr) / 2
    left := arr[:mid]
    right := arr[mid:]

    var wg sync.WaitGroup

    wg.Add(2)
    go func() {
        defer wg.Done()
        left = mergeSortWg(left)
    }()

    go func() {
        defer wg.Done()
        right = mergeSortWg(right)
    }()

    wg.Wait()

    return merge(left, right)
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!