Golang 并发机制-2:Golang Goroutine 和竞争条件
在今天的软件开发中,我们正在使用并发的概念,它允许一次执行多个任务。在Go编程中,理解Go例程是至关重要的。本文试图详细解释什么是例程,它们有多轻,通过简单地使用“go”关键字创建它们,以及可能出现的竞争条件和共享数据问题等主要同步困难。
Goroutine 介绍
Goroutine 是 Go 编程语言中并发编程的基本构建块。它本质上是一个轻量级的执行线程,在 Go 程序中与其他 Goroutine 并行运行。与其它编程语言中的传统线程不同,Goroutine 由 Go 运行时管理,在内存和 CPU 利用率方面都更高效。
- 性质与效率
Goroutine的突出特性之一是它们的轻量级特性。传统线程可能是资源密集型的,会消耗大量的内存和CPU资源。相比之下,gooutine非常高效,支持创建数千个这样的例程,而不会造成显著的开销。
Goroutine的效率源于它们能够跨较少数量的OS线程进行多路复用,并根据工作负载动态调整其分配。这意味着Go程序可以有效地利用多个内核和处理器,而不需要大量的手动线程管理。

Goroutine示例(‘ go ’关键字)
在Go中创建Goroutine非常简单,这要归功于“Go”关键字。当你在函数调用前加上‘ go ’时,go会创建新的gooutine来并发地执行该函数。
import ("fmt""time"
)func sayHello() {for i := 0; i < 5; i++ {fmt.Println("Hello, World!")time.Sleep(time.Millisecond * 500)}
}func main() {go sayHello() // Start a new Goroutinetime.Sleep(time.Second * 2)fmt.Println("Main function")
}
在上面的例子中,‘ sayHello ’函数与‘ main ’函数并发执行,使其成为在Go中利用并发性的一种简单而有效的方法。
竞争条件
虽然在并发编程中提供了许多优点,但它们也带来了必须小心管理的同步挑战
什么是竞态条件?
当多个Goroutine(轻量级线程)并发地访问共享数据,并且其中至少有一个需要修改数据时,就会出现竞争条件。竞争条件会导致不可预测的结果,因为执行顺序无法保证。它们可能导致数据损坏、崩溃或错误的程序行为。
竞态条件示例:
package mainimport ("fmt""sync"
)var sharedCounter int
var wg sync.WaitGroupfunc increment() {for i := 0; i < 10000; i++ {sharedCounter++}wg.Done()
}func main() {wg.Add(2)go increment()go increment()wg.Wait()fmt.Println("Shared Counter:", sharedCounter)
}
在本例中,两个goroutine在没有同步的情况下并发地增加‘ sharedCounter ’变量。这可能导致竞争条件,其中‘ sharedCounter ’的最终值是不可预测的,并且可能是不正确的。
假设 sharedCounter 的初始值为 0,两个 goroutine 同时读取到 0,然后分别加 1 并写回内存,最终 sharedCounter 的值会是 1 而不是 2。为了避免竞争条件,可以使用同步机制,如互斥锁(sync.Mutex)来保护对共享资源的访问。
规避竞争条件
为了消除Go中的竞争条件,你可以使用同步原语,例如互斥锁(互斥锁的简称)。互斥锁确保一次只有一个程序可以访问代码的关键部分。下面是上一个例子的更新版本,使用互斥锁进行正确的同步:
package mainimport ("fmt""sync"
)var sharedCounter int
var wg sync.WaitGroup
var mu sync.Mutexfunc increment() {for i := 0; i < 10000; i++ {mu.Lock()sharedCounter++mu.Unlock()}wg.Done()
}func main() {wg.Add(2)go increment()go increment()wg.Wait()fmt.Println("Shared Counter:", sharedCounter)
}
在修改后的代码中,我们使用‘ mu ’互斥锁来保护‘ sharedCounter ’被修改的代码的临界区。通过锁定和解锁互斥锁,我们确保一次只有一个Goroutine可以访问和修改‘ sharedCounter ’,从而消除了竞争条件。
理解共享数据问题
Go中的共享数据问题发生在多个线程在没有适当同步的情况下并发访问和操作共享数据时。这些问题主要表现为两种形式:
-
数据竞争:当两个或多个例程同时访问共享数据时,就会发生数据竞争,从而导致不可预测的结果。数据竞争可能导致数据损坏或不正确的程序行为。
-
死锁:当线程被卡住时,会发生死锁,等待彼此释放资源。这可能导致程序陷入停滞。
为了缓解Go中的共享数据问题,开发人员应该使用适当的同步机制,如互斥锁、通道和其他同步原语。以下是一些最佳做法:
- 使用互斥锁:使用互斥锁保护共享数据,以确保一次只有一个线程可以访问它。
- 使用通道:通道为程序提供了一种安全的方式来通信和共享数据。它们通过确保对共享数据的受控访问来防止数据竞争。
- 避免循环依赖:在创建循环依赖时要小心,因为在循环依赖中,各例程会等待彼此释放资源,从而导致死锁。
总之,在用Go编写并发程序时,管理竞争条件和共享数据问题是至关重要的。通过理解这些问题并实现适当的同步技术,开发人员可以创建健壮可靠的并发应用程序,充分利用Go的并发支持,同时避免与共享数据操作相关的陷阱。
最后总结
总之,Go程序是Go编程语言的一个强大功能,它提供了一种轻量级且高效的方式来实现并发性。通过使用“go”关键字,开发人员可以轻松地创建并发执行任务的goroutine。然而,在用Go构建并发应用程序时,必须意识到同步挑战,比如竞争条件和共享数据问题,并采用适当的技术来解决这些问题。
相关文章:
Golang 并发机制-2:Golang Goroutine 和竞争条件
在今天的软件开发中,我们正在使用并发的概念,它允许一次执行多个任务。在Go编程中,理解Go例程是至关重要的。本文试图详细解释什么是例程,它们有多轻,通过简单地使用“go”关键字创建它们,以及可能出现的竞…...
深入剖析 CSRF 漏洞:原理、危害案例与防护
目录 前言 漏洞介绍 漏洞原理 产生条件 产生的危害 靶场练习 post 请求csrf案例 防御措施 验证请求来源 设置 SameSite 属性 双重提交 Cookie 结语 前言 在网络安全领域,各类漏洞层出不穷,时刻威胁着用户的隐私与数据安全。跨站请求伪造&…...
C++和Python实现SQL Server数据库导出数据到S3并导入Redshift数据仓库
用C实现高性能数据处理,Python实现操作Redshift导入数据文件。 在Visual Studio 2022中用C和ODBC API导出SQL Server数据库中张表中的所有表的数据为CSV文件格式的数据流,用逗号作为分隔符,用双引号包裹每个数据,字符串类型的数据…...
AI大模型开发原理篇-5:循环神经网络RNN
神经概率语言模型NPLM也存在一些明显的不足之处:模型结构简单,窗口大小固定,缺乏长距离依赖捕捉,训练效率低,词汇表固定等。为了解决这些问题,研究人员提出了一些更先进的神经网络语言模型,如循环神经网络、…...
4-图像梯度计算
文章目录 4.图像梯度计算(1)Sobel算子(2)梯度计算方法(3)Scharr与Laplacian算子4.图像梯度计算 (1)Sobel算子 图像梯度-Sobel算子 Sobel算子是一种经典的图像边缘检测算子,广泛应用于图像处理和计算机视觉领域。以下是关于Sobel算子的详细介绍: 基本原理 Sobel算子…...
数据结构与算法 —— 常用算法模版
数据结构与算法 —— 常用算法模版 二分查找素数筛最大公约数与最小公倍数 二分查找 人间若有天堂,大马士革必在其中;天堂若在天空,大马士革必与之齐名。 —— 阿拉伯谚语 算法若有排序,二分查找必在其中;排序若要使用…...
DDD - 领域事件_解耦微服务的关键
文章目录 Pre领域事件的核心概念领域事件的作用领域事件的识别领域事件的技术实现领域事件的运行机制案例领域事件驱动的优势 Pre DDD - 微服务设计与领域驱动设计实战(中)_ 解决微服务拆分难题 EDA - Spring Boot构建基于事件驱动的消息系统 领域事件的核心概念 领域事件&a…...
芯片AI深度实战:实战篇之vim chat
利用vim-ollama这个vim插件,可以在vim内和本地大模型聊天。 系列文章: 芯片AI深度实战:基础篇之Ollama-CSDN博客 芯片AI深度实战:基础篇之langchain-CSDN博客 芯片AI深度实战:实战篇之vim chat-CSDN博客 芯片AI深度…...
【产品经理学习案例——AI翻译棒出海业务】
前言: 本文主要讲述了硬件产品在出海过程中,翻译质量、翻译速度和本地化落地策略是硬件产品规划需要考虑的核心因素。针对不同国家,需要优化翻译质量和算法,关注市场需求和文化差异,以便更好地满足当地用户的需求。同…...
解决运行npm时报错
在运行一个Vue项目时报错,产生下面问题 D:\node\npm.cmd run dev npm WARN logfile could not be created: Error: EPERM: operation not permitted, open D:\node\node_cache\_logs\2025-01-31T01_01_58_076Z-debug-0.log npm WARN logfile could not be created:…...
【07-编译工程与导入网表】
这里写自定义目录标题 一丶编译原理图编译默认属性一丶编译项目二丶输出BOM材料报告优化EXCEL-BOM清单 三丶输出PDF原理图给维修人员看 四丶导入网格表查看是否有错误常见错误 其他问题什么是位号(C1)?EXCEL添加序号列和居中显示?位号(序号)与单位(型号)EXCEL设置自动换行 编…...
FireFox | Google Chrome | Microsoft Edge 禁用更新 final版
之前的方式要么失效,要么对设备有要求,这次梳理一下对设备、环境几乎没有要求的通用方式,universal & final 版。 1.Firefox 方式 FireFox火狐浏览器企业策略禁止更新_火狐浏览器禁止更新-CSDN博客 这应该是目前最好用的方式。火狐也…...
conda配置channel
你收到 CondaKeyError: channels: value https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main not present in config 错误是因为该镜像源(https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main)可能没有被正确添加到 Conda 的配置文件中&…...
【MQ】探索 Kafka
基本概念 主题:Topic。主题是承载消息的逻辑容器,在实际使用中多用来区分具体的业务。 分区:Partition。一个有序不变的消息序列。每个主题下可以有多个分区。消息位移:Offset。表示分区中每条消息的位置信息,是一个…...
Workbench 中的热源仿真
探索使用自定义工具对移动热源进行建模及其在不同行业中的应用。 了解热源动力学 对移动热源进行建模为各种工业过程和应用提供了有价值的见解。激光加热和材料加工使用许多激光束来加热、焊接或切割材料。尽管在某些情况下,热源 (q) 不是通…...
计算机网络 笔记 网络层 3
IPv6 IPv6 是互联网协议第 6 版(Internet Protocol Version 6)的缩写,它是下一代互联网协议,旨在解决 IPv4 面临的一些问题,以下是关于 IPv6 的详细介绍: 产生背景: 随着互联网的迅速发展&…...
翼星求生服务器搭建【Icarus Dedicated Server For Linux】
一、前言 本次搭建的服务器为Steam平台一款名为Icarus的沙盒、生存、建造游戏,由于官方只提供了Windows版本服务器导致很多热爱Linux的小伙伴无法释怀,众所周知Linux才是专业服务器的唯一准则。虽然Github上已经有大佬制作了容器版本但是容终究不够完美,毕竟容器无法与原生L…...
ZZNUOJ(C/C++)基础练习1011——1020(详解版)
目录 1011 : 圆柱体表面积 C语言版 C版 1012 : 求绝对值 C语言版 C版 1013 : 求两点间距离 C语言版 C版 1014 : 求三角形的面积 C语言版 C版 1015 : 二次方程的实根 C语言版 C版 1016 : 银行利率 C语言版 C版 1017 : 表面积和体积 C语言版 C版 代码逻辑…...
论文阅读:Realistic Noise Synthesis with Diffusion Models
这篇文章是 2025 AAAI 的一篇工作,主要介绍的是用扩散模型实现对真实噪声的仿真模拟 Abstract 深度去噪模型需要大量来自现实世界的训练数据,而获取这些数据颇具挑战性。当前的噪声合成技术难以准确模拟复杂的噪声分布。我们提出一种新颖的逼真噪声合成…...
复杂场景使用xpath定位元素
在复杂场景下使用XPath定位元素时,可以通过以下高级技巧提高定位准确性和稳定性: 动态属性处理 模糊匹配: //div[contains(id, dynamic-part)] //button[starts-with(name, btn-)] //input[ends-with(class, -input)] (需XPath 2.0)多属性…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
