Go WaitGroup及Cond底层实现原理

Go WaitGroup及Cond底层实现原理

WaitGroup

WaitGroup是Golang提供的一个线程同步的工具,它可以使一个线程等待一组线程的完成操作。

实现原理

WaitGroup内部有一个计数器,初始值为0。每次调用Add方法,计数器就加1;每次调用Done方法,计数器就减1;每次调用Wait方法,它会阻塞等待计数器的值为0。

var wg sync.WaitGroup

func main() {
    for i := 0; i < 10; i++ {
        wg.Add(1)   // 计数器加1
        go func(wg *sync.WaitGroup) {
            defer wg.Done() // 计数器减1
            fmt.Println("Hello, World!")
        }(&wg)
    }
    wg.Wait()   // 等待计数器为0
}

示例

一个等待多个goroutine完成的例子:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(2)

    go func(wg *sync.WaitGroup) {
        defer wg.Done()
        fmt.Println("Routine 1")
    }(wg)

    go func(wg *sync.WaitGroup) {
        defer wg.Done()
        fmt.Println("Routine 2")
    }(wg)

    wg.Wait()
    fmt.Println("All routines are done!")
}

Cond

Cond是条件变量,是Go语言中一个比较底层的同步原语。它的作用是在多个goroutine之间协调调度执行。

实现原理

Cond是结合Mutex(锁)来使用的。开发人员可以使用Cond来等待或者触发某个事件的发生。当一个goroutine等待一个事件发生时,它会阻塞自己并释放Mutex锁,供其他的goroutine使用。当事件发生时,其他的goroutine可以通知正在等待的goroutine,使得它重新开始执行。

type Cond struct {
    noCopy noCopy

    L Locker // 互斥锁
    notify  notifyList
    checker copyChecker  // 用来检查复制
}

Cond类型内部包含一个互斥锁,一个通知列表(notifyList)和一个复制检查器(copyChecker)。

示例

下面是一个生产者/消费者模型的示例:

package main

import (
    "fmt"
    "sync"
)

var buffer []int
var bufferLock sync.Mutex
var bufferCond = sync.NewCond(&bufferLock)
var done = make(chan bool)

func producer() {
    for i := 0; i < 10; i++ {
        bufferLock.Lock()
        buffer = append(buffer, i)
        fmt.Println("Producing...", i)
        bufferLock.Unlock()

        bufferCond.Signal() // 唤醒一个消费者
    }
    done <- true
}

func consumer(id int) {
    for {
        bufferLock.Lock()
        for len(buffer) == 0 {
            bufferCond.Wait() // 挂起等待直到收到生产者的信号
        }
        value := buffer[0]
        buffer = buffer[1:]
        fmt.Printf("Consumer %d consuming %d\n", id, value)
        bufferLock.Unlock()
    }
}

func main() {
    for i := 0; i < 3; i++ {
        go consumer(i)
    }

    go producer()

    <-done
    fmt.Println("Done!")
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Go WaitGroup及Cond底层实现原理 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 用vbs将名称转换为正确的大小写的代码

    用VBS将名称转换为正确的大小写的代码攻略 以下是一个使用VBS脚本将名称转换为正确大小写的代码的攻略。这个脚本可以帮助你将一个字符串的大小写转换为正确的形式。 步骤1:创建VBS脚本文件 首先,你需要创建一个新的文本文件,并将其保存为.vbs文件扩展名。你可以使用任何文本编辑器来创建这个文件。 步骤2:编写VBS脚本代码 在创建的VBS脚本文件中,输入以下…

    other 2023年8月17日
    00
  • android实现简单进度条ProgressBar效果

    Android实现简单进度条ProgressBar效果攻略 1. 添加ProgressBar到布局文件 首先,在你的布局文件中添加一个ProgressBar组件。可以使用以下代码示例: <ProgressBar android:id=\"@+id/progressBar\" android:layout_width=\"m…

    other 2023年9月6日
    00
  • php ckeditor上传图片文件名乱码解决方法

    下面是详细讲解“php ckeditor上传图片文件名乱码解决方法”的完整攻略。 问题描述 在使用php ckeditor上传图片时,如果图片文件名带有中文,就会出现乱码的情况,导致无法正确显示图片。 解决方法 通过对上传的图片文件名进行转码,可以解决乱码的问题。具体步骤如下: 1. 获取上传的文件名 首先,我们需要获取上传的图片文件名。在php中,可以使用…

    other 2023年6月26日
    00
  • 强大的健身软件——Keep

    强大的健身软件——Keep 近年来,随着健身热潮的兴起,越来越多的人开始关注健康和身材,并且选择通过健身来达到自己的目标。而作为健身练习的工具,健身软件也得到了广泛的应用。今天,我想向大家介绍一款强大的健身软件——Keep。 功能介绍 个性化训练计划 Keep可以为每位用户根据其身材、目标和运动能力制定个性化的训练计划。不同于传统的一套标准训练计划,Keep…

    其他 2023年3月28日
    00
  • UNIX 系统常用管理命令

    以下是UNIX系统常用管理命令的攻略及示例说明: 目录和文件管理命令 ls命令 ls命令是Unix中最常用的命令之一,用于列出目录内容。当我们在一个目录中执行ls命令时,它将会显示该目录下的所有文件和目录的名称。 ls命令的常用参数: -l: 以长格式列出目录内容,包括文件类型、权限、硬链接数、所有者、所属组、文件大小、时间戳等信息。 -a: 列出目录中所有…

    other 2023年6月26日
    00
  • win8 IE10无法安装Flash Player多种解决方案

    下面详细讲解“win8 IE10无法安装Flash Player多种解决方案”的完整攻略,包含以下几个步骤: 1. 确认IE10已经启用Flash Player插件 首先,需要确认IE10已经启用Flash Player插件,可以通过以下步骤进行确认: 打开IE10,在地址栏输入“about:plugins”,回车进入插件管理界面。 找到Adobe Flas…

    other 2023年6月26日
    00
  • intellij idea设置统一JavaDoc模板的方法详解

    IntelliJ IDEA设置统一JavaDoc模板的方法详解 在IntelliJ IDEA中,可以通过设置统一的JavaDoc模板来规范项目中的注释格式。下面是设置统一JavaDoc模板的步骤: 步骤一:打开IntelliJ IDEA的设置面板 首先,打开IntelliJ IDEA,点击顶部菜单栏中的”File”,然后选择”Settings”(或者使用快捷…

    other 2023年6月28日
    00
  • jquery获取select选中的文本与值

    以下是“jQuery获取select选中的文本与值的完整攻略”的详细讲解,过程中包含两个示例说明的标准Markdown格式文本: jQuery获取选中的文本与值的完整攻略 在jQuery中,可以使用val()方法获取select选中的值,使用text()方法获取select选中文本。以下是这两个方法的详细步骤: 获取select选中的值 可以使用val()方…

    other 2023年5月10日
    00
合作推广
合作推广
分享本页
返回顶部