GO语言中通道和sync包的使用教程分享

GO语言中通道和sync包的使用教程分享

什么是通道

通道(channel)是 Go 语言中一种特有的同步原语,用于在不同 Goroutine 之间交换数据。通道是一种类型的值,可以对它进行初始化、传递给函数、赋值给变量,甚至可以把它放到切片或结构体中。

创建通道

通道通过 make() 函数来创建,语法如下:

ch := make(chan int)

这里我们创建了一个名为 ch 的通道,元素类型为 int。注意通道只能存储 int 类型的元素。

发送和接收数据

通道可以发数据和收数据,发数据使用“<-”运算符,接收数据则直接使用通道名称。以下是示例代码:

package main

import "fmt"

func main() {
    ch := make(chan int)
    go func() {
        ch <- 2 // 发送数据
    }()
    x := <-ch // 接收数据
    fmt.Print(x)
}

在这个示例中,我们在一个新的 Goroutine 中向通道 ch 中发送了一个整数,然后在主 Goroutine 中接收了这个整数,并打印了它。

若通道中没有数据则会阻塞,如以下示例代码:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go func() {
        time.Sleep(time.Second)
        ch <- 2 // 发送数据
    }()
    x := <-ch // 接收数据
    fmt.Print(x)
}

这个示例中,我们在发送数据前通过 time.Sleep(time.Second) 让程序等待 1 秒钟,程序会先阻塞在这里,等待新的数据被发送。在数据被发送之后,接收方才能获得数据并打印。

sync包

上文讲到的通道只是同步原语的一个应用,Go 标准库还提供了一个专门用于同步的包,叫作 sync

互斥锁

互斥锁是 Go 语言提供的解决并发问题的一种基础同步机制。互斥锁,全称是 Mutual Exclusion Lock,非常类似操作系统中的互斥体和临界区的概念。

在并发编程中,多个并发执行的 Goroutine 会共享资源,若同时对资源进行读写操作,则会导致数据不一致。为了避免这种情况,我们需要使用互斥锁来保护资源。以下是示例代码:

package main

import (
    "fmt"
    "sync"
)

var (
    x  int
    wg sync.WaitGroup
    mu sync.Mutex
)

func main() {
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            mu.Lock()
            x++
            mu.Unlock()
        }()
    }
    wg.Wait()
    fmt.Print(x)
}

在这个示例中,我们开了 100 个 Goroutine,每个 Goroutine 都会将变量 x 加一。由于多个 Goroutine 可能会同时执行 x++,我们需要使用互斥锁 mu.Lock()mu.Unlock() 来保护 x 变量。

读写锁

读写锁是 Go 语言提供的另一种解决并发问题的同步机制,它允许多个 Goroutine 同时读取资源,但只允许一个 Goroutine 写入资源。这种机制在只有少量写入且大量读取的高并发场景下能够显著提升效率。

在使用读写锁时,我们需要先用 sync.RWMutex 创建一个 RWMutex 的实例来进行初始化,并通过 mu.RLock()mu.RUnlock() 来锁定和释放读锁,通过 mu.Lock()mu.Unlock() 来锁定和释放写锁。

以下是一个使用读写锁的示例代码:

package main

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

var (
    x  int
    wg sync.WaitGroup
    mu sync.RWMutex
)

func main() {
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            mu.Lock()
            x++
            mu.Unlock()
        }()
    }
    time.Sleep(time.Second)
    fmt.Printf("x=%d\n", x)

    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            mu.RLock()
            fmt.Printf("x=%d\n", x)
            mu.RUnlock()
        }()
    }
    wg.Wait()
}

在这个示例中,我们同样开了 100 个 Goroutine,前 100 个 Goroutine 会将变量 x 加一,后面的 100 个 Goroutine 则会读取变量 x 的值。我们通过使用读写锁 sync.RWMutex 来保护 x 的读写操作,并通过 mu.RLock()mu.RUnlock() 来锁定和释放读锁,通过 mu.Lock()mu.Unlock() 来锁定和释放写锁。

总结

通过学习本篇文章,我们了解了 Go 语言中通道和 sync 包的基本用法。在多并发的应用场景中,通道和互斥锁/读写锁是非常常用的同步原语。这些机制可以帮助我们在并发执行的 Goroutine 中同步数据,并避免数据的不一致性问题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:GO语言中通道和sync包的使用教程分享 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • 用C++编写扩展node.js(node-ffi版)

    编写扩展是Node.js的一大特色,可用于使用C/C++或其他语言来扩展Node.js核心功能或为Node.js实现第三方模块。其中,Node.js提供了两个核心库,即N-API和node-gyp,可以让我们更加方便地编写扩展。另外,node-ffi是另一款非常流行的编写扩展的库。下面,我们就来具体讲解如何使用C++编写扩展node.js(node-ffi版…

    C 2023年5月23日
    00
  • C语言 strspn()函数

    当我们需要检测两个字符串之间共有的字符时,可以使用C语言的strspn()函数。该函数返回字符串中的字符数目,直到字符串中的第一个不属于目标字符集合的字符(即停止搜索的字符)被检测到。以下是关于该函数的详细使用攻略。 函数原型 size_t strspn(const char *str1, const char *str2); 该函数接受两个参数:str1和…

    C 2023年5月9日
    00
  • win10开机蓝屏代码0xc000001怎么办 错误代码0xc000001的解决教程

    Win10开机蓝屏代码0xc000001怎么办 错误代码0xc000001的解决教程 在Windows 10系统使用电脑时,经常会遇到蓝屏问题,如果蓝屏提示代码为0xc000001,可能是由于系统文件损坏或系统启动设置不正确引起,下面是解决方法: 方法1:使用Windows Startup Repair Windows Startup Repair是Wind…

    C 2023年5月23日
    00
  • c++显式类型转换示例详解

    C++ 显式类型转换示例详解 什么是显式类型转换 在C++中,有时候我们需要将一种数据类型(例如字符串)转换为另一种数据类型(例如数字)。这就需要使用类型转换操作符。 C++中的类型转换分为两种,一种是隐式类型转换,另一种是显式类型转换。其中隐式类型转换由编译器自动完成,而显式类型转换需要程序员手动调用类型转换操作符进行转换。 显式类型转换的语法 C++支持…

    C 2023年5月24日
    00
  • C语言实现简易通讯录实例

    C语言实现简易通讯录实例 简介 本项目将使用C语言实现一个简易通讯录,可以添加联系人、删除联系人、修改联系人以及查看通讯录中所有联系人的信息。 环境 开发平台:Windows / Linux / MacOS 编译器:gcc 功能列表 添加联系人 删除联系人 修改联系人 查看通讯录中所有联系人的信息 数据结构 为了实现通讯录的功能,我们需要用到两种数据结构:联…

    C 2023年5月30日
    00
  • NBA2KOL海耶斯投篮包怎么样 C级球员投篮包介绍

    NBA2KOL海耶斯投篮包怎么样 在NBA2KOL中,海耶斯投篮包是一种帮助球员训练投篮技巧的道具,使用之后可以提高C级球员的投篮能力。本篇攻略将介绍海耶斯投篮包的使用方法和效果,同时帮助球员更好地理解C级球员投篮包。 海耶斯投篮包使用方法 在游戏中,将鼠标移到主菜单的“训练”选项上,选择“篮球基础训练”进入训练模式。之后,在球场的右侧将看到海耶斯投篮包的图…

    C 2023年5月23日
    00
  • C调用C++代码的方法步骤

    C语言是一款面向过程的语言,而C++语言是一款面向对象的语言。虽然二者有着许多相似之处,但仍然会存在一些不兼容的情况,在C中调用C++代码时也是如此。下面介绍一下C调用C++代码的方法步骤。 步骤 在C++文件中,声明被调用的函数为extern “C” #ifdef __cplusplus extern "C" { #endif // y…

    C 2023年5月23日
    00
  • 谷歌Pixel C平板电脑做工怎么样?Google Pixel C拆机全过程评测图解

    谷歌Pixel C平板电脑做工怎么样? 1. 硬件外观 Pixel C的外观采用了一块10.2英寸的屏幕,分辨率为2560 x 1800,屏幕背面采用了金属材质设计,显得更加高端大气。屏幕的边框采用了比较窄的设计,让整个屏幕看起来更加大气美观。 2. 做工 Pixel C的做工非常精细,整个设备采用了一体化模具设计,不仅外观简洁大气,而且手感舒适。机身作为单…

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