当前位置:首页 > 科技  > 软件

Go语言中的sync包同步原语

来源: 责编: 时间:2023-12-25 17:29:20 387观看
导读通过sync包掌握Go语言的并发并发是现代软件开发的基本方面,而Go(也称为Golang)为并发编程提供了一套强大的工具。在Go中用于管理并发的基本包之一是sync包。在本文中,我们将概述sync包,并深入探讨其最关键的同步原语之一:等

通过sync包掌握Go语言的并发

并发是现代软件开发的基本方面,而Go(也称为Golang)为并发编程提供了一套强大的工具。在Go中用于管理并发的基本包之一是sync包。在本文中,我们将概述sync包,并深入探讨其最关键的同步原语之一:等待组(Wait Groups)。nd628资讯网——每日最新资讯28at.com

nd628资讯网——每日最新资讯28at.com

sync包概述

sync包是Go的标准库包,为并发编程提供了同步原语。它为开发人员提供了协调和同步Goroutines的工具,确保并发任务的安全和有序执行。sync包提供的一些关键同步原语包括Mutexes、RWMutexes、Cond和Wait Groups。nd628资讯网——每日最新资讯28at.com

等待组(Wait Groups)

1.什么是等待组?

等待组是Go中sync包提供的一个同步原语。它是一个简单但强大的工具,用于管理Goroutines的同步,特别是当您希望在继续之前等待一组Goroutines完成其任务时。nd628资讯网——每日最新资讯28at.com

等待组在您有多个Goroutines同时执行独立任务,并且您需要确保所有任务都已完成后再继续主程序的场景中非常有用。nd628资讯网——每日最新资讯28at.com

2.如何使用等待组

让我们通过一个代码示例来探索如何使用等待组:nd628资讯网——每日最新资讯28at.com

package mainimport (    "fmt"    "sync"    "time")func worker(id int, wg *sync.WaitGroup) {    defer wg.Done() // Decrement the Wait Group counter when done    fmt.Printf("Worker %d is working/n", id)    time.Sleep(time.Second)    fmt.Printf("Worker %d has finished/n", id)}func main() {    var wg sync.WaitGroup    for i := 1; i <= 3; i++ {        wg.Add(1) // Increment the Wait Group counter for each Goroutine        go worker(i, &wg)    }    wg.Wait() // Wait for all Goroutines to finish    fmt.Println("All workers have finished.")}

在这个示例中,我们定义了一个名为worker的函数,该函数通过休眠一秒来模拟工作。我们启动了三个Goroutines,每个代表一个工作者,并使用sync.WaitGroup来协调它们的执行。nd628资讯网——每日最新资讯28at.com

  • wg.Add(1) 在启动每个Goroutine之前增加等待组计数器。
  • wg.Done() 在worker函数中被延迟执行,以在Goroutine完成其工作时减少计数器。
  • wg.Wait() 阻塞主程序,直到所有Goroutines都完成,确保我们等待所有工作者的完成。

RWMutex(读写互斥锁)

RWMutex(读写互斥锁)是Go语言中的一个同步原语,它允许多个Goroutines同时读取共享数据,同时确保写入时的独占访问。在数据频繁读取但较少修改的场景中,它非常有用。nd628资讯网——每日最新资讯28at.com

如何使用RWMutex

以下是一个简单的示例,演示如何使用RWMutex:nd628资讯网——每日最新资讯28at.com

package mainimport (    "fmt"    "sync"    "time")var (    data        int    dataMutex   sync.RWMutex)func readData() int {    dataMutex.RLock() // Read Lock    defer dataMutex.RUnlock()    return data}func writeData(value int) {    dataMutex.Lock() // Write Lock    defer dataMutex.Unlock()    data = value}func main() {    // Read data concurrently    for i := 1; i <= 5; i++ {        go func() {            fmt.Println("Read Data:", readData())        }()    }    // Write data    writeData(42)    time.Sleep(time.Second)}

在这个示例中,多个Goroutines同时读取共享的data,而一个单独的Goroutine则对其进行写入。RWMutex确保多个读取者可以同时访问数据,但只有一个写入者可以在任何时候修改它。nd628资讯网——每日最新资讯28at.com

Cond(条件变量)

1.什么是条件变量?

条件变量是一种同步原语,允许Goroutines在继续执行之前等待特定条件变为真。当您需要基于某些条件协调多个Goroutines的执行时,它们非常有用。nd628资讯网——每日最新资讯28at.com

2.如何使用Cond

以下是一个基本示例,说明了如何使用条件变量:nd628资讯网——每日最新资讯28at.com

package mainimport (    "fmt"    "sync"    "time")var (    conditionMutex sync.Mutex    condition      *sync.Cond    isReady        bool)func waitForCondition() {    conditionMutex.Lock()    defer conditionMutex.Unlock()    for !isReady {        fmt.Println("Waiting for the condition...")        condition.Wait()    }    fmt.Println("Condition met, proceeding.")}func setCondition() {    time.Sleep(2 * time.Second)    conditionMutex.Lock()    isReady = true    condition.Signal() // Signal one waiting Goroutine    conditionMutex.Unlock()}func main() {    condition = sync.NewCond(&conditionMutex)    go waitForCondition()    go setCondition()    time.Sleep(5 * time.Second)}

在这个示例中,一个Goroutine使用condition.Wait()等待条件变为真,而另一个Goroutine将条件设置为true并使用condition.Signal()通知等待的Goroutine。nd628资讯网——每日最新资讯28at.com

原子操作

1.什么是原子操作?

原子操作是作为单个、不可分割的工作单元执行的操作。它们通常用于在并发程序中安全地更新共享变量,而无需使用互斥锁。Go提供了一个名为atomic的包来进行原子操作。nd628资讯网——每日最新资讯28at.com

2.如何使用原子操作

以下是一个演示原子操作的示例:nd628资讯网——每日最新资讯28at.com

package mainimport (    "fmt"    "sync"    "sync/atomic"    "time")var (    counter int32    wg      sync.WaitGroup)func incrementCounter() {    defer wg.Done()    for i := 0; i < 100000; i++ {        atomic.AddInt32(&counter, 1)    }}func main() {    wg.Add(2)    go incrementCounter()    go incrementCounter()    wg.Wait()    fmt.Println("Counter:", atomic.LoadInt32(&counter))}

在这个示例中,两个Goroutines使用原子操作递增一个共享的counter变量。atomic.AddInt32函数确保递增操作是原子的,并且对并发访问是安全的。nd628资讯网——每日最新资讯28at.com

选择正确的同步机制

在选择适当的同步机制时,请考虑以下准则:nd628资讯网——每日最新资讯28at.com

  • 互斥锁(对于读取使用RWMutex,对于写入使用Mutex) 在你需要对访问进行细粒度控制时,非常适合保护共享数据。
  • 条件变量 在你需要基于特定条件协调Goroutines时非常有价值。
  • 原子操作 在你想避免互斥锁开销的情况下,对共享变量进行简单操作非常高效。
  • 始终选择最能满足特定用例要求的同步机制。

总之,Go语言在sync包中提供了一套多才多艺的同步机制,以及用于管理对共享资源的并发访问的原子操作。了解这些工具并为您的并发需求选择合适的工具是编写高效可靠的并发Go程序的关键。nd628资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-54015-0.htmlGo语言中的sync包同步原语

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C++中使用宏定义一个函数:灵活性与风险并存

下一篇: Python Selenium实现自动化测试及Chrome驱动使用!

标签:
  • 热门焦点
  • 8月总票房已突破10亿!《封神》第一:口碑已经成了

    8月5日消息,据灯塔专业版数据,截至8月5日9时35分,8月总票房(含预售)已突破10亿。其中,《封神》以大比分的优势领先。根据官方消息,目前该片总票房已经超过14.
  • 线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • Automa-通过连接块来自动化你的浏览器

    1、前言通过浏览器插件可实现自动化脚本的录制与编写,具有代表性的工具就是:Selenium IDE、Katalon Recorder,对于简单的业务来说可快速实现自动化的上手工作。Selenium IDEKat
  • 一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 得物宠物生意「狂飙」,发力“它经济”

    作者|花花小萌主近日,得物宣布正式上线宠物鉴别,通过得物App内的&ldquo;在线鉴别&rdquo;,可找到鉴别宠物的选项。通过上传自家宠物的部位细节,就能收获拥有专业资质认证的得物鉴
  • 重估百度丨大模型,能撑起百度的“今天”吗?

    自象限原创 作者|程心 罗辑2023年之前,对于自己的&ldquo;今天&rdquo;,百度也很迷茫。&ldquo;新业务到 2022 年底还是 0,希望 2023 年出来一个 1。&rdquo;这是2022年底,李彦宏
  • 三星Galaxy Z Fold5官方渲染图曝光:13.4mm折叠厚度依旧感人

    据官方此前宣布,三星将于7月26日在韩国首尔举办Unpacked活动,届时将带来带来包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy Z Flip 5、
  • 回归OPPO两年,一加赢了销量,输了品牌

    成为OPPO旗下主打性能的先锋品牌后,一加屡创佳绩。今年618期间,一加手机全渠道销量同比增长362%,凭借一加 11、一加 Ace 2、一加 Ace 2V三款爆品,一加
  • 苹果140W USB-C充电器:采用氮化镓技术

    据10 月 30 日 9to5 Mac 消息报道,当苹果推出新的 MacBook Pro 2021 时,该公司还推出了新的 140W USB-C 充电器,附赠在 MacBook Pro 16 英寸机型的盒子里,也支
Top