>  기사  >  백엔드 개발  >  Go에서의 동시성에 대한 자세한 설명 [동영상 20장]

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]

青灯夜游
青灯夜游앞으로
2022-09-08 10:48:261763검색

golang의 다양한 동시성 모드는 어떤 모습인가요? 다음 글에서는 20개의 애니메이션 사진을 통해 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 동시성을 보여드리겠습니다. 모든 사람에게 도움이 되기를 바랍니다.

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]

이 글을 영상으로 이해하고 싶다면 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]pherCon에서 제 연설을 시청해주세요 www.youtube.com/watch?v=KyuFeiG3Y6...

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 언어의 가장 강력한 기능 하나는 Tony Hoare의 CSP 논문을 기반으로 한 내장 동시성입니다. Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]는 동시성을 염두에 두고 설계되었으며 이를 통해 복잡한 동시성 파이프라인을 구축할 수 있습니다. 다양한 동시성 모드가 어떤 모습인지 궁금한 적이 있나요?

생각해 보셨을 텐데요. 대부분 우리는 상상을 통해 문제를 생각합니다. "1부터 100까지의 숫자"에 대해 질문하면 무의식적으로 일련의 그림이 마음 속에 나타납니다. 예를 들어, 나로부터 시작하여 숫자 1에서 20까지 갔다가 오른쪽으로 90도 회전하여 1000+까지 이어지는 직선을 상상해 보겠습니다. 제가 아주 어렸을 때, 우리 유치원 때 휴대품 보관소 벽에 숫자가 많이 적혀 있었는데 우연히 모퉁이에 20이라는 숫자가 붙어 있던 기억이 납니다. 당신은 아마도 자신만의 숫자 그림을 가지고 있을 것입니다. 또 다른 일반적인 예는 올해의 계절을 시각적으로 표현하는 것입니다. 일부는 이를 상자로 상상하고 다른 일부는 원으로 상상합니다.

어쨌든 저는 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]와 WebGL을 사용하여 일반적인 동시성 패턴에 대한 저의 구체적인 시도를 보여드리고 싶습니다. 이는 동시성 프로그램에 대한 저의 이해를 어느 정도 보여줍니다. 당신 머리 속에 있는 그림과 내가 어떻게 다른지 듣는 것은 정말 흥미로울 것입니다. 특히 Rob Pike나 Sameer Ajmani가 그들의 머릿속에서 동시성을 어떻게 생각하는지 알고 싶습니다. [관련 추천: Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 비디오 튜토리얼]

그럼 오늘은 아주 기본적인 "Hello, Concurrent World" 예제로 주제를 시작하겠습니다.

안녕하세요, 동시 세계

코드는 매우 간단합니다. 단일 채널, 단일 고루틴, 단일 쓰기, 단일 읽기입니다.

package main

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

    // 开启一个匿名 goroutine
    go func() {
        // 向通道发送数字42
        ch <p><a href="https://divan.dev/demos/hello/" target="_blank">대화형 WebGL 애니메이션으로 이동</a> <img src="https://img.php.cn/upload/article/000/000/024/03104ecc960e1992d7b04ec4cd79a77f-0.gif" alt="Hello, World"></p><p>파란색 선은 시간에 따라 실행되는 고루틴을 나타냅니다. 'main'과 'go #19'를 연결하는 얇은 파란색 선은 고루틴의 시작과 끝을 표시하는 데 사용됩니다. 부모-자식 관계가 표시되며 마지막으로 빨간색 선은 보내기/받기 동작을 나타냅니다. 두 개의 독립적인 동작이지만 "A에서 B로 보내기" 애니메이션을 사용하여 이를 하나의 동작으로 표현하려고 했습니다. 고루틴 이름의 #19"는 고루틴의 실제 내부 ID입니다. 획득 방법은 Scott Mansfield의 "Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]routine IDs" 글을 참고하세요. </p><h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;">Timers</span></strong>
</h3><p>실제로 다음 방법으로 간단한 타이머를 만들 수 있습니다. 채널을 만들고 goroutine을 시작한 다음 지정된 시간 간격 후에 채널에 데이터를 쓰게 한 다음 이것을 반환합니다. 발신자에게 채널을 보냅니다. 따라서 이전에 설정된 시간 간격이 지날 때까지 채널을 읽을 때 호출 기능이 차단됩니다. 다음으로 타이머를 24번 호출하고 호출 프로세스를 시각화해 봅니다. </p><pre class="brush:php;toolbar:false">package main

import "time"

func timer(d time.Duration) <p><a href="https://divan.dev/demos/timers/" target="_blank">대화형 WebGL 애니메이션으로 이동</a> <img src="https://img.php.cn/upload/article/000/000/024/6e2b2d910982ba58209c1c53cd9c7f6d-1.gif" alt="Recurrent Timers"></p><p> 꽤 깔끔하죠? </p><h3>
<span class="header-link octicon octicon-link"></span><strong><span style="font-size: 18px;">Ping-pong</span></strong>
</h3><p>이 동시성 예제는 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]ogle 직원 Sameer Ajmani의 "<a href="https://talks.golang.org/2013/advconc.slide#1" target="_blank" textvalue="Advanced Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] Concurrency Patterns">Advanced Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] Concurrency Patterns</a>" 강연에서 가져온 것입니다. 물론 이 패턴은 그다지 발전된 것은 아니지만 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]의 동시성 메커니즘에만 익숙한 사람들에게는 새롭고 흥미로워 보일 수 있습니다. </p><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 <p><a href="https://divan.dev/demos/pingpong/" target="_blank" textvalue="转到交互式 WebGL 动画">대화형 WebGL 애니메이션으로 이동</a> <img src="https://img.php.cn/upload/article/000/000/024/6e2b2d910982ba58209c1c53cd9c7f6d-2.gif" alt="Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]"></p><p>여기에서 <a href="https://divan.dev/demos/pingpong/" target="_blank">링크</a>를 클릭하여 대화형 WebGL 애니메이션에 들어가고 다양한 각도에서 관찰할 수 있습니다. </p><p>이제 플레이어 3명을 추가해서 살펴보겠습니다. </p><pre class="brush:php;toolbar:false">    go player(table)
    go player(table)
    go player(table)

转到交互式 WebGL 动画 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 3 我们可以看到每个玩家都按照次序轮流操作,你可能会想为什么会这样。为什么多个玩家(goroutine)会按照严格的顺序接到“球”呢。

答案是 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 运行时环境维护了一个 接收者 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="Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 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">Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 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> 的名称。在Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]中,此模式易于实现-只需以通道为参数启动多个goroutine,然后将值发送至该通道-Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]运行时会自动地进行分配和复用 :)</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="Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]"></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">Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 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)
    }
}

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] to 交互式WebGL动画 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 

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

但是,让我们回到并发性并向我们的服务器添加一些交互。假设每个处理程序都希望异步写入记录器。在我们的示例中,记录器本身是一个单独的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">Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] to 交互式WebGL动画</a> <img src="https://img.php.cn/upload/article/000/000/024/dfdd69afd5511ae20942d0af033a1db2-9.gif" alt="Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 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">Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 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">Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 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动画

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]

,请以交互模式随意播放此动画。我喜欢它的说明性-它确实可以帮助您更好地理解该算法。 * 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

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]

이 애니메이션에서는 시간의 속도가 다르기 때문에(모든 애니메이션이 동일한 시간/높이에 맞춰지길 원함) 그 차이가 눈에 띕니다. GOMAXPROCS = 1이면 다음 작업자는 이전 작업이 완료된 후에만 실제 작업을 시작할 수 있습니다. GOMAXPROCS = 24의 경우 속도 향상이 매우 크며 다중화 오버헤드는 무시할 수 있습니다.

그러나 GOMAXPROCS를 늘리는 것이 항상 성능을 향상시키는 것은 아니며 어떤 경우에는 실제로 성능을 악화시킬 수 있다는 점을 이해하는 것이 중요합니다.

고루틴 누출

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]의 동시성 시간에서 무엇을 증명할 수 있나요? 마음에 떠오르는 한 가지는 고루틴 누출입니다. 예를 들어 고루틴을 시작했지만 범위를 벗어나는 경우 누출이 발생할 수 있습니다. 또는 종료 조건을 추가하는 것을 잊어버리고 대신 for{} 루프를 실행했습니다.

내 코드에서 고루틴 누출을 처음 접했을 때 무서운 이미지가 떠올랐고 다음 주말에 expvarmon을 썼습니다. 이제 WebGL을 사용하여 이 무서운 이미지를 시각화할 수 있습니다.

보세요:

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]

이 내용을 보는 것만으로도 고통스럽습니다. :) 이 모든 줄은 리소스를 낭비하고 프로그램에 시한폭탄이 됩니다.

병렬성은 동시성이 아닙니다

마지막으로 설명하고 싶은 것은 병렬성과 동시성의 차이입니다. 이 주제 많은 내용 을 다루며 Rob Pike는 이 주제에 대해 훌륭한 강연 을 했습니다. #꼭 봐야할 영상 중 하나에요.

간단히 말하면

병렬은 단순히 여러 작업을 병렬로 실행하는 것입니다.

동시성은 프로그램을 구성하는 방법입니다.

따라서 동시성 프로그램은 병렬일 수도 있고 아닐 수도 있으며 이러한 개념은 다소 직교합니다. 우리는 GOMAXPROCS 설정의 효과를 시연했을 때 이미 이를 보았습니다.

링크된 기사와 강연을 모두 반복할 수 있지만 사진 한 장이 천 단어를 말해줍니다. 여기서 제가 할 수 있는 일은 차이점을 시각화하는 것입니다. 그래서 평행합니다. 많은 것들이 병렬로 실행됩니다.

Interactive WebGL Animation으로 이동 并行 1

이것도 병렬입니다.

Interactive WebGL Animation으로 이동

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]

그러나 동시적입니다.

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]

Workers of workers이것은 동시성이기도 합니다:

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]

How it was made 이러한 애니메이션을 만들기 위해 저는

gotracer

go three.js 라이브러리라는 두 가지 프로그램을 작성했습니다. 먼저, gotracer는 다음을 수행합니다.

Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 프로그램의 AST 트리(추상 구문 트리)를 구문 분석하고 동시성 관련 이벤트에 대한 출력과 함께 특수 명령을 삽입합니다(고루틴 시작/중지, 채널 생성, 채널과의 전송/수신). .
  • 생성된 프로그램을 실행합니다.
  • 이 특수 출력을 분석하고 이벤트 및 타임스탬프 설명이 포함된 JSON을 생성합니다.
  • 생성된 JSON 예:

JSON sample다음으로 go three.js는 놀라운

Three.js

라이브러리의 기능을 사용하여 WebGL을 사용하여 3D 선과 개체를 그립니다. 단일 HTML 페이지에 맞도록 아주 작은 래핑을 수행했습니다. 그게 전부입니다.

그러나 이 방법은 매우 제한적입니다. 다소 복잡한 코드가 올바른 추적을 생성하도록 하려면 예제를 정확하게 선택하고 채널과 고루틴의 이름을 바꿔야 했습니다. 이 접근 방식을 사용하면 이름이 다른 고루틴 간에 채널을 연결하는 쉬운 방법이 없습니다. chan 유형 채널을 통해 전송되는 채널은 말할 것도 없습니다. 타이밍에 대한 큰 문제도 있습니다. stdout으로 출력하는 것은 값을 보내는 것보다 더 많은 시간이 걸릴 수 있으므로 어떤 경우에는 시간을 넣어야 합니다. 애니메이션을 올바르게 얻으려면 절전(몇 밀리초) 동안 기다려야 합니다.

기본적으로 제가 아직 오픈소스 코드를 가지고 있지 않은 이유도 바로 이것입니다. 나는 Dmitry Vyukov의 Execution Tracker를 가지고 놀고 있는데, 이벤트에 대한 세부 정보를 제공하는 것처럼 보이지만 가치 있는 정보를 보내는 것은 포함되지 않습니다. 어쩌면 원하는 목표를 달성하는 더 좋은 방법이 있을 수도 있습니다. 아이디어가 있으면 트위터에 한 줄을 남겨주시거나 댓글에 한 줄을 남겨주세요. 이 2주간의 도구가 모든 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] 프로그램에 대한 실제 디버깅/추적 도구로 확장될 수 있다면 좋을 것입니다.

여기에 나열되지 않은 더 흥미로운 동시성 알고리즘과 패턴도 보고 싶습니다. 댓글에 하나씩 적어주세요.

즐거운 코딩 되세요!

UPD: 이 도구는 github.com/pan/gotrace에서 사용할 수 있으며 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장] Execution Tracer 및 패치된 런타임을 사용하여 추적을 생성합니다.

또한 저는 새로운 일자리에 열려 있으므로 귀하의 회사/팀이 저에게 관심이 있거나 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]에서의 동시성에 대한 자세한 설명 [동영상 20장]를 사용하여 해결하기 어려운 문제가 있는 경우 원격으로 일할 수 있고(또는 귀하가 바르셀로나에 있을 때) 채용할 수 있도록 해주세요. 알아요 :)

영어 원본 주소: https://divan.dev/posts/go_concurrency_visualize/

더 많은 프로그래밍 관련 지식을 보려면 Programming Video를 방문하세요! !

위 내용은 Go에서의 동시성에 대한 자세한 설명 [동영상 20장]의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제