讲师中心 微信公众号
AI工具推荐 视频效率加速

Go语言并发中 time.Sleep 的行为解析

酷宇同学_6024

酷宇同学_6024

发布时间:2025-09-25 12:04:26

|

1126人浏览过

|

来源于php中文网

原创

Go语言并发中 time.Sleep 的行为解析

当多个Goroutine同时调用time.Sleep时,它们会各自独立地暂停指定时长,由于Goroutine的并发执行特性,这些暂停是同时发生的,因此程序的总执行时间并不会是单个time.Sleep时长的累加,而是约等于最长的一个time.Sleep时长。文章通过示例代码详细阐述了这一机制,并提供了关键注意事项。

理解Go语言的并发模型与Goroutine

go语言以其内置的并发原语而闻名,其中goroutine是其核心。goroutine是一种轻量级的执行线程,由go运行时管理。通过在函数调用前加上go关键字,即可启动一个新的goroutine。与传统操作系统线程不同,goroutine的创建和销毁开销极小,可以轻松创建成千上万个goroutine。

并发(Concurrency)是指能够同时处理多个任务的能力,这些任务可能在同一时间段内交错执行。Go的运行时调度器负责在可用的CPU核心上调度这些Goroutine,使得它们看起来是并行执行的,即使在单核处理器上也是如此。

time.Sleep 的作用机制

time.Sleep(d Duration)函数的作用是暂停当前Goroutine的执行,持续时间为d。这里的“当前Goroutine”是关键,它指的是调用time.Sleep的那个特定的Goroutine,而不是整个程序或所有其他Goroutine。当一个Goroutine进入睡眠状态时,Go调度器会将CPU资源分配给其他可运行的Goroutine,从而实现高效的资源利用。

并发场景下 time.Sleep 的行为分析

许多初学者在并发编程中可能会对time.Sleep的行为产生误解。例如,如果启动N个Goroutine,每个Goroutine都调用time.Sleep(4 * time.Second),那么程序的总执行时间是多少?直观上,有些人可能认为总时间会是N * 4秒,因为每个Goroutine都要等待。然而,在Go的并发模型下,实际的总执行时间将约等于4秒。

这是因为当主Goroutine通过一个循环启动多个工作Goroutine时,所有工作Goroutine几乎是同时启动的。一旦它们各自执行到time.Sleep(4 * time.Second)这一行,它们便会同时进入睡眠状态。Go调度器会暂停这些Goroutine,并在4秒后将它们唤醒。由于它们同时开始睡眠,也就会同时被唤醒并继续执行,因此从外部观察,整个过程的总耗时就是单个Goroutine的睡眠时长。

立即学习“go语言免费学习笔记(深入)”;

让我们通过一个具体的代码示例来演示这一行为:

协同养育操作系统
协同养育操作系统

协同养育操作系统(Co-Parenting OS)— 离异家庭专业协同养育支持系统。12模块覆盖接送管理、成长记忆库、孩子观察站、亲子关系粘合剂、共同挑战中心、情绪冲突观察、父母成长、成长档案馆、成长阶段引擎、风险预警、驾驶舱、被恶意攻击急救包。当用户涉及离异家庭育儿、协同养育、抚养探视、接送安排、孩子成长记录、亲子关系、离异冲突、被恶意攻击、前任矛盾等话题时触发。

下载
package main

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

// worker函数模拟一个需要执行任务并暂停的Goroutine
func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done() // 在Goroutine退出时通知WaitGroup完成

    fmt.Printf("Goroutine %d: 在 %s 开始执行任务并睡眠。\n", id, time.Now().Format("15:04:05.000"))
    time.Sleep(4 * time.Second) // 每个Goroutine睡眠4秒
    fmt.Printf("Goroutine %d: 在 %s 睡眠结束,任务完成。\n", id, time.Now().Format("15:04:05.000"))
}

func main() {
    const numWorkers = 3 // 定义启动的工作Goroutine数量
    var wg sync.WaitGroup // 用于等待所有Goroutine完成

    fmt.Printf("主Goroutine: 在 %s 启动所有工作Goroutine...\n", time.Now().Format("15:04:05.000"))
    startTime := time.Now() // 记录开始时间

    // 启动多个工作Goroutine
    for i := 1; i <= numWorkers; i++ {
        wg.Add(1) // 每启动一个Goroutine,WaitGroup计数器加1
        go worker(i, &wg)
    }

    wg.Wait() // 等待所有工作Goroutine完成

    endTime := time.Now() // 记录结束时间
    fmt.Printf("主Goroutine: 在 %s 所有工作Goroutine完成。总耗时:%v\n", endTime.Format("15:04:05.000"), endTime.Sub(startTime))
}

代码解析:

  1. worker 函数: 这是一个简单的函数,它接收一个id用于标识Goroutine,以及一个*sync.WaitGroup指针用于通知主Goroutine其完成状态。它会打印开始信息,然后调用time.Sleep(4 * time.Second),最后打印结束信息。
  2. main 函数:
    • 定义了numWorkers为3,表示将启动3个工作Goroutine。
    • 创建了一个sync.WaitGroup实例wg,用于协调主Goroutine和工作Goroutine的执行。wg.Add(1)在启动每个Goroutine前增加计数器,defer wg.Done()在每个Goroutine结束时减少计数器。wg.Wait()会阻塞主Goroutine,直到计数器归零。
    • 记录了程序开始时间startTime。
    • 通过一个for循环,使用go worker(i, &wg)启动了numWorkers个并发的Goroutine。
    • 调用wg.Wait()等待所有工作Goroutine完成。
    • 记录程序结束时间endTime,并计算总耗时。

预期输出分析:

运行上述代码,你将观察到类似以下输出(时间戳会有所不同):

主Goroutine: 在 10:30:00.000 启动所有工作Goroutine...
Goroutine 1: 在 10:30:00.000 开始执行任务并睡眠。
Goroutine 2: 在 10:30:00.000 开始执行任务并睡眠。
Goroutine 3: 在 10:30:00.000 开始执行任务并睡眠。
Goroutine 1: 在 10:30:04.000 睡眠结束,任务完成。
Goroutine 2: 在 10:30:04.000 睡眠结束,任务完成。
Goroutine 3: 在 10:30:04.000 睡眠结束,任务完成。
主Goroutine: 在 10:30:04.000 所有工作Goroutine完成。总耗时:4.00xxxxxxs

从输出中可以清晰地看到:

  • 所有Goroutine几乎在同一时刻(10:30:00.000)开始睡眠。
  • 所有Goroutine也几乎在同一时刻(10:30:04.000)结束睡眠。
  • 主Goroutine报告的总耗时大约是4秒,而不是3 * 4 = 12秒。

这完美地印证了time.Sleep在并发Goroutine中是独立且同时作用的。

注意事项与总结

  1. 独立暂停: time.Sleep只暂停调用它的那个Goroutine,不会影响其他并发运行的Goroutine。
  2. 并发效率: Go的并发模型设计初衷就是为了高效地执行独立任务。time.Sleep的这种行为正是并发效率的体现,它允许其他Goroutine在当前Goroutine睡眠时继续工作,而不是等待它完成。
  3. 避免误解: 如果你的程序逻辑需要Goroutine按顺序暂停或等待更长时间,那么需要显式地通过通道(chan)、互斥锁(sync.Mutex)或sync.WaitGroup等同步机制来协调它们的执行顺序和时间。例如,如果希望每个Goroutine的睡眠是串行的,那么就不应该并发启动它们,或者通过通道进行逐个信号通知。
  4. 实际应用: 在实际开发中,time.Sleep常用于模拟耗时操作、定时任务或在测试中引入延迟。理解其在并发环境下的行为对于正确设计和调试并发程序至关重要。

总之,Go语言的time.Sleep在并发Goroutine中表现为独立且同时的暂停。这一特性是Go并发模型的基础,理解它有助于开发者更有效地利用Goroutine构建高性能、响应迅速的应用程序。

热门AI工具

更多
Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

相关专题

更多
C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

379

2026.04.23

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4578

2023.08.10

Go中Type关键字的用法
Go中Type关键字的用法

Go中Type关键字的用法有定义新的类型别名或者创建新的结构体类型。本专题为大家提供Go相关的文章、下载、课程内容,供大家免费下载体验。

3209

2023.09.06

go怎么实现链表
go怎么实现链表

go通过定义一个节点结构体、定义一个链表结构体、定义一些方法来操作链表、实现一个方法来删除链表中的一个节点和实现一个方法来打印链表中的所有节点的方法实现链表。

6427

2023.09.25

go语言编程软件有哪些
go语言编程软件有哪些

go语言编程软件有Go编译器、Go开发环境、Go包管理器、Go测试框架、Go文档生成器、Go代码质量工具和Go性能分析工具等。本专题为大家提供go语言相关的文章、下载、课程内容,供大家免费下载体验。

762

2023.10.13

0基础如何学go语言
0基础如何学go语言

0基础学习Go语言需要分阶段进行,从基础知识到实践项目,逐步深入。php中文网给大家带来了go语言相关的教程以及文章,欢迎大家前来学习。

8185

2023.10.26

Go语言实现运算符重载有哪些方法
Go语言实现运算符重载有哪些方法

Go语言不支持运算符重载,但可以通过一些方法来模拟运算符重载的效果。使用函数重载来模拟运算符重载,可以为不同的类型定义不同的函数,以实现类似运算符重载的效果,通过函数重载,可以为不同的类型实现不同的操作。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3016

2024.02.23

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3264

2024.02.23

Tailwind CSS 如何制作导航栏和卡片
Tailwind CSS 如何制作导航栏和卡片

用 Tailwind CSS 制作导航栏和卡片,可先搭建语义化结构,再组合 Flex、Grid、间距、圆角与阴影类。这里整理横向导航、移动端菜单、卡片网格及悬停效果的相关文章,帮助你把常见页面组件做得清晰且适配不同屏幕。

0

2026.11.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn