Maison  >  Article  >  développement back-end  >  Une explication détaillée de la concurrence dans Go [20 images animées]

Une explication détaillée de la concurrence dans Go [20 images animées]

青灯夜游
青灯夜游avant
2022-09-08 10:48:261764parcourir

À quoi ressemblent les différents modes de concurrence dans

golang ? L'article suivant vous montrera la simultanéité Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] à travers 20 images animées. J'espère qu'il sera utile à tout le monde !

Une explication détaillée de la concurrence dans Go [20 images animées]

Si vous préférez comprendre cet article par vidéo, veuillez cliquer pour regarder mon discours à la Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]pherCon www.youtube.com/watch?v=KyuFeiG3Y6...

Les fonctionnalités les plus puissantes du langage Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] L'un est la concurrence intégrée basée sur l'article CSP de Tony Hoare

Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] a été conçu dans un souci de concurrence et nous permet de créer des pipelines de concurrence complexes. Vous êtes-vous déjà demandé à quoi ressemblent les différents modes de concurrence ?

Vous avez dû y penser. La plupart du temps, nous réfléchissons aux problèmes par l'imagination. Si je vous pose une question sur les « nombres de 1 à 100 », une série d'images apparaîtra inconsciemment dans votre esprit. Par exemple, je l'imaginerais comme une ligne droite partant de moi, allant des nombres 1 à 20 puis tournant à droite de 90 degrés jusqu'à 1000+. Je me souviens que quand j'étais très jeune, dans notre jardin d'enfants, il y avait beaucoup de chiffres écrits sur le mur du vestiaire, et le chiffre 20 se trouvait justement au coin de la rue. Vous avez probablement votre propre vision des chiffres. Un autre exemple courant est la représentation visuelle des saisons de l’année – certains l’imaginent comme une boîte, d’autres comme un cercle.

Quoi qu'il en soit, je souhaite utiliser Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] et WebGL pour vous montrer mes tentatives concrètes de modèles de concurrence courants. Cela représente plus ou moins ma compréhension des programmes concurrents. Ce serait vraiment intéressant de savoir en quoi je diffère de l’image que vous avez en tête. J'aimerais particulièrement savoir comment Rob Pike ou Sameer Ajmani imaginent la concurrence dans leur tête, je parie que je serais intéressé. [Recommandation connexe : Tutoriel vidéo Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]

]

Commençons donc notre sujet d'aujourd'hui par un exemple très basique de « Hello, Concurrent World ».

Bonjour, Monde concurrent

Le code est très simple - un seul canal, une seule goroutine, une seule écriture, une seule lecture.

package main

func main() {
    // 创建一个int类型的通道
    ch := make(chan int)

    // 开启一个匿名 goroutine
    go func() {
        // 向通道发送数字42
        ch <a href="https://divan.dev/demos/hello/" target="_blank"></a>Allez à l'animation WebGL interactive<img src="https://img.php.cn/upload/article/000/000/024/03104ecc960e1992d7b04ec4cd79a77f-0.gif" alt="Hello, World"> <p></p>La ligne bleue représente la goroutine qui s'exécute dans le temps. La fine ligne bleue reliant 'main' et 'go #19' est utilisée pour marquer le début et la fin de la goroutine. sont montrées la relation parent-enfant, et enfin, la ligne rouge représente l'action d'envoi/réception. Bien qu'il s'agisse de deux actions indépendantes, j'ai essayé de les représenter comme une seule action avec l'animation "envoyer de A à B". #19" dans le nom de la goroutine est le véritable identifiant interne de la goroutine. Pour la méthode pour l'obtenir, veuillez vous référer à l'article "Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]routine IDs" de Scott Mansfield. <h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;"></span>Timers</strong>
</h3><p></p>En fait, vous pouvez créer une minuterie simple par la méthode suivante : créez un canal, démarrez une goroutine et laissez-la écrire des données sur le canal après un intervalle de temps spécifié, puis renvoyez ceci canal vers l’appelant. Ainsi, la fonction appelante se bloquera lors de la lecture du canal jusqu'à ce que l'intervalle de temps précédemment défini soit écoulé. Ensuite, nous appelons le minuteur 24 fois et essayons de visualiser le processus d'appel. <p></p><pre class="brush:php;toolbar:false">package main

import "time"

func timer(d time.Duration) <a href="https://divan.dev/demos/timers/" target="_blank"></a>Allez aux animations WebGL interactives<img src="https://img.php.cn/upload/article/000/000/024/6e2b2d910982ba58209c1c53cd9c7f6d-1.gif" alt="Recurrent Timers"> <p></p> Plutôt sympa, non ? <h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;"></span>Ping-pong</strong>
</h3><p><a href="https://talks.golang.org/2013/advconc.slide#1" target="_blank" textvalue="Advanced Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] Concurrency Patterns">Cet exemple de simultanéité est tiré de l'exposé « </a>Advanced Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] Concurrency Patterns</p> » de Sameer Ajmani, employé de Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]ogle. Bien sûr, ce modèle n’est pas très avancé, mais il peut sembler nouveau et intéressant à ceux qui ne connaissent que les mécanismes de concurrence de Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]. <p></p>Ici, nous utilisons un canal pour représenter la table de tennis de table. Une variable entière représente la balle, puis deux goroutines sont utilisées pour représenter le joueur. Le joueur simule l'action au bâton en augmentant la valeur de la variable entière (compteur de clics). . <p></p><pre class="brush:php;toolbar:false">package main

import "time"

func main() {
    var Ball int
    table := make(chan int)
    go player(table)
    go player(table)

    table <a href="https://divan.dev/demos/pingpong/" target="_blank" textvalue="转到交互式 WebGL 动画"></a>Allez à l'animation WebGL interactive<img src="https://img.php.cn/upload/article/000/000/024/6e2b2d910982ba58209c1c53cd9c7f6d-2.gif" alt="Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] [20 images animées]"> <p><a href="https://divan.dev/demos/pingpong/" target="_blank">Ici, je vous suggère de cliquer sur le </a>lien</p> pour accéder à l'animation WebGL interactive. Vous pouvez ralentir ou accélérer l'animation et l'observer sous différents angles. <p></p>Maintenant, ajoutons trois joueurs et jetons un œil. 🎜<pre class="brush:php;toolbar:false">    go player(table)
    go player(table)
    go player(table)

转到交互式 WebGL 动画 Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] [20 images animées] 3 我们可以看到每个玩家都按照次序轮流操作,你可能会想为什么会这样。为什么多个玩家(goroutine)会按照严格的顺序接到“球”呢。

答案是 Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] 运行时环境维护了一个 接收者 FIFO 队列 (存储需要从某一通道上接收数据的goroutine),在我们的例子里,每个玩家在刚发出球后就做好了接球准备。我们来看一下更复杂的情况,加入100个玩家。

for i := 0; i <p><a href="https://divan.dev/demos/pingpong100/" target="_blank">转到交互式 WebGL 动画</a> <img src="https://img.php.cn/upload/article/000/000/024/f022e6361217c7f4c90e16d8d0885f99-4.gif" alt="Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] [20 images animées] 100"> </p><p>先进先出顺序很明显了,是吧? 我们可以创建一百万个goroutine,因为它们很轻量,但是对于实现我们的目的来说没有必要。我们来想想其他可以玩的。 例如, 常见的消息传递模式。</p><h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;">Fan-In</span></strong>
</h3><p>并发世界中流行的模式之一是所谓的 <em>fan-in</em> 模式。这与 <em>fan-out</em> 模式相反,稍后我们将介绍。简而言之,fan-in 是一项功能,可以从多个输入中读取数据并将其全部多路复用到单个通道中。</p><p>举例来说:</p><pre class="brush:php;toolbar:false">package main

import (
    "fmt"
    "time"
)

func producer(ch chan int, d time.Duration) {
    var i int
    for {
        ch <p><a href="https://divan.dev/demos/fanin/" target="_blank">Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] to interactive WebGL animation</a> <img src="https://img.php.cn/upload/article/000/000/024/f022e6361217c7f4c90e16d8d0885f99-5.gif" alt="Fan-In Pattern"></p><p>如我们所见,第一个 <em>producer</em> 每100毫秒生成一次值,第二个每250毫秒生成一次值,但是 <em>reader</em> 会立即从这两个生产者那里接受值。实际上,多路复用发生在 <em>main</em> 的range循环中。</p><h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;">Workers</span></strong>
</h3><p>与 <em>fan-in</em> 相反的模式是 <em>fan-out</em> 或者<em>worker</em> 模式。多个 goroutine 可以从单个通道读取,从而在CPU内核之间分配大量的工作量,因此是 <em>worker</em> 的名称。在Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]中,此模式易于实现-只需以通道为参数启动多个goroutine,然后将值发送至该通道-Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]运行时会自动地进行分配和复用 :)</p><pre class="brush:php;toolbar:false">package main

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

func worker(tasksCh <p><img src="https://img.php.cn/upload/article/000/000/024/bc82f8929dc05185db5d2b4542d2ca73-6.gif" alt="Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]"></p><p>这里值得一提的是:并行性。如您所见,所有goroutine并行’运行‘,等待通道给予它们’工作‘。鉴于上面的动画,很容易发现goroutine几乎立即接连地收到它们的工作。不幸的是,该动画在goroutine确实在处理工作还是仅仅是在等待输入的地方没有用颜色显示出来,但是此动画是在GOMAXPROCS=4的情况下录制的,因此只有4个goroutine有效地并行运行。我们将很快讨论这个主题。</p><p>现在,让我们做一些更复杂的事情,并启动一些有自己workers(subworkers)的workers。</p><pre class="brush:php;toolbar:false">package main

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

const (
    WORKERS    = 5
    SUBWORKERS = 3
    TASKS      = 20
    SUBTASKS   = 10
)

func subworker(subtasks chan int) {
    for {
        task, ok := <p><a href="https://divan.dev/demos/workers2/" target="_blank">Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] to interactive WebGL animation</a> <img src="https://img.php.cn/upload/article/000/000/024/bc82f8929dc05185db5d2b4542d2ca73-7.gif" alt="Workers of workers"> 很好。当然,我们可以将worker和subworker的数量设置为更高的值,但是我试图使动画清晰易懂。</p><p>更酷的 fan-out 模式确实存在,例如动态数量的worker/subworker,通过通道发送通道,但是 fan-out 的想法现在应该很清楚了。</p><h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;">服务器</span></strong>
</h3><p>下一个常见的模式类似于扇出,但是会在很短的时间内生成goroutine,只是为了完成某些任务。它通常用于实现服务器-创建侦听器,循环运行accept()并为每个接受的连接启动goroutine。它非常具有表现力,可以实现尽可能简单的服务器处理程序。看一个简单的例子:</p><pre class="brush:php;toolbar:false">package main

import "net"

func handler(c net.Conn) {
    c.Write([]byte("ok"))
    c.Close()
}

func main() {
    l, err := net.Listen("tcp", ":5000")
    if err != nil {
        panic(err)
    }
    for {
        c, err := l.Accept()
        if err != nil {
            continue
        }
        go handler(c)
    }
}

Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] to 交互式WebGL动画 Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] 

这不是很有趣-似乎并发方面没有发生任何事情。当然,在引擎盖下有很多复杂性,这是我们特意隐藏的。 “简单性很复杂”.

但是,让我们回到并发性并向我们的服务器添加一些交互。假设每个处理程序都希望异步写入记录器。在我们的示例中,记录器本身是一个单独的goroutine,它可以完成此任务。

package main

import (
    "fmt"
    "net"
    "time"
)

func handler(c net.Conn, ch chan string) {
    ch <p><a href="https://divan.dev/demos/servers2/" target="_blank">Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] to 交互式WebGL动画</a> <img src="https://img.php.cn/upload/article/000/000/024/dfdd69afd5511ae20942d0af033a1db2-9.gif" alt="Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] 2"> </p><p>不是吗?但是很容易看到,如果请求数量增加并且日志记录操作花费一些时间(例如,准备和编码数据),我们的* logger * goroutine很快就会成为瓶颈。我们可以使用一个已知的扇出模式。我们开始做吧。</p><h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;">服务器+工作者</span></strong>
</h3><p>带工作程序的服务器示例是记录器的高级版本。它不仅可以完成一些工作,而且还可以通过* results *通道将其工作结果发送回池中。没什么大不了的,但是它将我们的记录器示例扩展到了更实际的示例。</p><p>让我们看一下代码和动画:</p><pre class="brush:php;toolbar:false">package main

import (
    "net"
    "time"
)

func handler(c net.Conn, ch chan string) {
    addr := c.RemoteAddr().String()
    ch <p><a href="https://divan.dev/demos/servers3/" target="_blank">Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] to 交互式WebGL动画</a> <img src="https://img.php.cn/upload/article/000/000/024/d04fb172e580bf3c4b0bca0edac0a234-10.gif" alt="Server + Worker"> 我们在4个goroutine之间分配了工作,有效地提高了记录器的吞吐量,但是从此动画中,我们可以看到记录器仍然可能是问题的根源。成千上万的连接在分配之前会汇聚在一个通道中,这可能导致记录器再次成为瓶颈。但是,当然,它会在更高的负载下发生。</p><h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;">并发素筛(素筛指素数筛法)</span></strong>
</h3><p>足够的扇入/扇出乐趣。让我们看看更复杂的并发算法。我最喜欢的例子之一是Concurrent Prime Sieve,可以在[<a href="https://talks.golang.org/2012/concurrency.slide" target="_blank">Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] Concurrency Patterns</a>]对话中找到。素数筛,或<a href="https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" target="_blank">[Eratosthenes筛)</a>是一种古老的算法,用于查找达到给定限制的素数。它通过按顺序消除所有质数的倍数来工作。天真的算法并不是真正有效的算法,尤其是在多核计算机上。</p><p>该算法的并发变体使用goroutine过滤数字-每个发现的素数一个goroutine,以及用于将数字从生成器发送到过滤器的通道。找到质数后,它将通过通道发送到* main *以进行输出。当然,该算法也不是很有效,特别是如果您想找到大质数并寻找最低的Big O复杂度,但是我发现它非常优雅。</p><pre class="brush:php;toolbar:false">// 并发的主筛
package main

import "fmt"

// 将序列2、3、4,...发送到频道“ ch”。
func Generate(ch chan<- int) {
    for i := 2; ; i++ {
        ch <- i // Send &#39;i&#39; to channel &#39;ch&#39;.
    }
}

//将值从通道“ in”复制到通道“ out”,
//删除可被“素数”整除的那些。
func Filter(in <-chan int, out chan<- int, prime int) {
    for {
        i := <-in // Receive value from &#39;in&#39;.
        if i%prime != 0 {
            out <- i // Send &#39;i&#39; to &#39;out&#39;.
        }
    }
}

//主筛:菊花链过滤器过程。
func main() {
    ch := make(chan int) // Create a new channel.
    go Generate(ch)      // Launch Generate goroutine.
    for i := 0; i < 10; i++ {
        prime := <-ch
        fmt.Println(prime)
        ch1 := make(chan int)
        go Filter(ch, ch1, prime)
        ch = ch1
    }
}

转到交互式WebGL动画

Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]

,请以交互模式随意播放此动画。我喜欢它的说明性-它确实可以帮助您更好地理解该算法。 * generate * goroutine发出从2开始的每个整数,每个新的goroutine仅过滤特定的质数倍数-2、3、5、7 …,将第一个找到的质数发送给* main *。如果旋转它从顶部看,您会看到从goroutine发送到main的所有数字都是质数。漂亮的算法,尤其是在3D中。

GOMAXPROCS(调整并发的运行性能)

现在,让我们回到我们的工作人员示例。还记得我告诉过它以GOMAXPROCS = 4运行吗?那是因为所有这些动画都不是艺术品,它们是真实程序的真实痕迹。

让我们回顾一下GOMAXPROCS是什么。

GOMAXPROCS设置可以同时执行的最大CPU数量。

当然,CPU是指逻辑CPU。我修改了一些示例,以使他们真正地工作(而不仅仅是睡觉)并使用实际的CPU时间。然后,我运行了代码,没有进行任何修改,只是设置了不同的GOMAXPROCS值。 Linux机顶盒有2个CPU,每个CPU具有12个内核,因此有24个内核。

因此,第一次运行演示了该程序在1个内核上运行,而第二次-使用了所有24个内核的功能。

WebGL动画-1| WebGL动画-24GOMAXPROCS1

Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]

La vitesse du temps dans ces animations est différente (je veux que toutes les animations correspondent à la même durée/hauteur), donc la différence est perceptible. Lorsque GOMAXPROCS = 1, le travailleur suivant ne peut commencer le travail réel qu'une fois le précédent terminé. Dans le cas de GOMAXPROCS = 24, l'accélération est très importante, tandis que le temps système de multiplexage est négligeable.

Cependant, il est important de comprendre qu'augmenter GOMAXPROCS n'améliore pas toujours les performances et, dans certains cas, peut même les aggraver.

Fuite de Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]routines

Que pouvons-nous prouver à partir des temps de concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] ? Une chose qui me vient à l’esprit, ce sont les fuites goroutines. Par exemple, si vous démarrez une goroutine mais qu'elle sort du cadre , une fuite peut se produire. Ou vous avez simplement oublié d'ajouter la condition de fin et avez exécuté une boucle for{} à la place.

La première fois que j'ai rencontré une fuite de goroutine dans mon code, des images effrayantes me sont venues à l'esprit et le week-end suivant, j'ai écrit expvarmon. Maintenant, je peux visualiser cette image effrayante en utilisant WebGL.

Jetez un oeil :

Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]

Ça me fait mal rien que de voir ça :) Toutes ces lignes gaspillent des ressources et sont une bombe à retardement pour votre programme.

Le parallélisme n'est pas la concurrence

La dernière chose que je veux illustrer est la différence entre le parallélisme et la concurrence. Ce sujet couvre beaucoup de choses et Rob Pike a donné une merveilleuse conférence sur ce sujet. Vraiment l'une des vidéos à ne pas manquer.

En bref,

Parallel consiste simplement à exécuter les choses en parallèle.

La concurrence est un moyen de structurer des programmes.

Ainsi, les programmes concurrents peuvent être parallèles ou non, et ces concepts sont quelque peu orthogonaux. Nous l'avons déjà vu en démontrant l'effet du paramètre GOMAXPROCS.

Je pourrais répéter tous ces articles et conférences liés, mais une image vaut mille mots. Ce que je peux faire ici, c'est visualiser la différence. C'est donc parallèle. Beaucoup de choses se déroulent en parallèle.

Allez sur Interactive WebGL Animation 并行 1

Ceci est également parallèle :

Allez sur Interactive WebGL Animation

Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]

Mais ceci est simultané :

Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]

Et ceci :

Workers of workers

Ceci est également concurrent :

Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées]

Comment cela a été réalisé

Pour créer ces animations, j'ai écrit deux programmes : gotracer et la bibliothèque gotrois.js. Tout d'abord, gotracer effectue les opérations suivantes :

  • Analyse l'arborescence AST (Abstract Syntax Tree) du programme Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] et insère des commandes spéciales avec une sortie sur les événements liés à la concurrence - démarrage/arrêt des goroutines, création de canaux, envoi/réception vers/depuis les canaux. .
  • Exécutez le programme généré
  • analysez cette sortie spéciale et générez du JSON avec des descriptions d'événements et d'horodatage.

Exemple JSON généré : JSON sample

Ensuite, gotwo.js utilise la puissance de l'incroyable bibliothèque Three.js pour dessiner des lignes et des objets 3D à l'aide de WebGL. J'ai fait un très petit emballage pour le faire tenir dans une seule page HTML - c'est tout.

Cependant, cette méthode est très limitée. J'ai dû choisir exactement mes exemples, renommer les canaux et les goroutines, pour que le code plus ou moins complexe produise des traces correctes. Avec cette approche, il n'existe pas de moyen simple de relier les canaux entre les goroutines s'ils ont des noms différents. Sans parler des chaînes envoyées sur les chaînes de type chan. Il y a aussi de gros problèmes avec le timing - la sortie sur la sortie standard peut prendre plus de temps que l'envoi de la valeur, donc dans certains cas, je dois mettre un time.Sleep (quelques millisecondes) pour que l'animation soit correcte.

En gros, c'est pourquoi je n'ai pas encore de code open source. Je joue avec le Execution Tracker de Dmitry Vyukov, qui semble fournir des détails sur l'événement, mais n'inclut pas l'envoi d'informations valables. Il existe peut-être une meilleure façon d’atteindre l’objectif souhaité. Si vous avez des idées, écrivez-moi sur Twitter ou écrivez-moi dans les commentaires. Ce serait formidable si cet outil de deux semaines pouvait être étendu en un véritable outil de débogage/traçage pour n'importe quel programme Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées].

J'aimerais également voir des algorithmes et des modèles de concurrence plus intéressants qui ne sont pas répertoriés ici. N'hésitez pas à en écrire un dans les commentaires.

Bon codage !

UPD : cet outil est disponible sur github.com/pan/gotrace et génère des traces à l'aide de Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées] Execution Tracer et d'un runtime corrigé.

De plus, je suis ouvert à de nouveaux emplois, donc si votre entreprise/équipe est intéressée par moi, a un problème difficile à résoudre avec Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Une explication détaillée de la concurrence dans Go [20 images animées] [20 images animées] [20 images animées] [20 images animées], je peux travailler à distance (ou vous êtes à Barcelone) et embauche, n'hésitez pas à le laisser je sais :)

Adresse originale en anglais : https://divan.dev/posts/go_concurrency_visualize/

Pour plus de connaissances liées à la programmation, veuillez visiter : Vidéo de programmation ! !

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer