深入理解 GO 语言并发
1. 使用并发
在深入了解 Go 如何处理并发之前,先查看并发的概念。在计算机发展的早期阶段,计算机系统只有一个处理器负责执行所有指令。由于这种体系结构,计算机程序被编写成以串行的方式运行,在这种方式下,程序按照预定义的顺序逐个指令地执行。
随着计算机程序变得越来越复杂,串行编程的使用带来了一些限制,因为程序在同一时间只能执行一条指令。计算机程序包含的指令越多,执行所需的时间就越长。这就需要用更快、更有效的方法来执行计算机程序。
1.1 操作系统的角色
操作系统(OS)负责管理计算机上运行的不同进程的组件。进程管理可分为三类:
- 多程序:多个进程在同一个处理器上运行
- 多处理:多个进程在多个处理器上运行
- 分布式处理:多个进程在多台机器上运行
不管是哪种处理类型,这些并发进程者都必须能够相互合作、竞争相同的资源并相互通信。唯一区别在于执行进程的方式。在多程序设计中,由于只有一个处理器,因此必须交错执行各种进程。而在多处理设计中,需要在不同的处理器上执行进程。
并发是指在同一个处理器上切换执行多个计算机程序的过程,使得用户产生这些程序同时运行的错觉。例如,操作系统和它所运行的应用程序。从用户角度看,可以同时听音乐、写文档和上网浏览网页。这就是我们所说的并发性。
并发通过允许不同的计算机程序共享一台计算机的 CPU 来营造同时执行的错觉。并发可以实现计算机的多任务处理。虽然它一次只能执行一个任务,但可以在任务之间快速切换。
当计算机上运行的进程彼此独立并且不会访问相同的资源时,并发管理很容易。然而,在实践中,大多数活跃的计算机进程共享并竞争相同的资源。这可能会在编写并发软件时引入一些问题和挑战。在设计软件时,必须考虑并发以及它带来的问题和挑战。
1.2 并发带来的问题
为说明并发的问题,假设有两个计算机进程(A 和 B),它们访问同一个全局变量,并且该全局变量由操作系统设置的。如果进程 A 和 B 同时访问全局变量,那么进程 A可能会改变全局变量的值,而进程 B 会检索旧值而不是进程 A 设置的新值。这会导致进程 A 和 B 执行过程中出现错误。
以下是一个带具体数字的例子。假设全局变量以值 6 开始,并且有两个进程,它们各自都要将值加到全局变量上。
- 进程 A 获取值为 6 的全局变量
- 进程 B 获取值为 6 的全局变量
- 进程 A 将取得的值加 3,总值为 9
- 进程 B 将取得的值加 5,总值为 11
- 进程 A 将全局变量更新为新总值 9
- 进程 B 将全局变量更新为新总值 11
结果是全局变量的值为 11,而它本应该为 14(6+3+5)。进程 B 的更新覆盖了进程 A 的更新。
为防止这种情况发生,需要限制对全局变量的访问,规定全局变量在同一时间只能由一个进程访问。这也被称为互斥。也就是说,如果一个进程正在访问共享资源,其他进程对该资源的访问必须被阻止,直到当前进程完成其执行。不同进程之间的共享资源的例子包括打印机、扫描仪和文件。两个进程同时访问一个文件可能会导致意外发生。互斥表示文件一次只能让一个进程访问。
1.3 互斥
并发带来了两个主要挑战:
- 为不同的进程分配适当的资源
- 安全共享全局资源
如前面一个例子所示,为安全地共享全局资源,必须实现互斥,其表明一次只能有一个进程访问共享资源。实现互斥有 3 种主要方法:
- 进程本身处理互斥。编写软件的程序员在软件源代码中实现互斥。由于程序员很容易犯编程错误或忘记实现互斥,因此这种方法往往会导致错误和意外行为。
- 使用特殊的机器指令强制进程访问共享资源。这些机器指令将保证发生互斥。
- 在操作系统和编程语言中实现互斥,经强制进程遵从互斥。操作系统是负责管理不同进程的组件,因此可以强制进程遵从互斥和并发。操作系统实现互斥的技术包括信号量、监视器和消息传递等。
虽然必须使用某种类型的互斥机制来确保在任何给定时间只有一个进程访问特定资源,但这仍然存在缺点。例如,当进程 A 访问共享资源时,所有其他进程必须等待进程 A 完成其工作。这导致了延迟。
另一个潜在的问题是可能会发生死锁。死锁是指一组计算机进程被操作系统永久阻塞。在发生死锁的情况下,这些进程会竞争全局资源并阻止彼此访问资源,直到操作系统决定阻止进程。被阻塞的每个进程会等待被另一个被阻塞进程占用的资源。
要发生死锁,需要满足 3 个条件:
- 进程间互斥:在任何给定的时间,只有一个进程可以使用这些资源。
- 挂起和等待:任何进程都可以在等待其他资源释放的同时持有一些资源。
- 不抢占:任何进程都不能强制释放任何资源。
例如,进程 A 可以持有一个资源并等待进程 B 当前正在使用的另一个资源。进程 B 可能持有进程 A 需要的资源,但在释放该资源之前要等待进程 C 完成。进程 C 本身可能正在等待进程 A 持有的资源。由于它们各自等待其他进程完成并释放其资源,因此这可能导致不同进程之间的死锁。
一个典型的死锁类比是在 eBay 这样的网站上出售商品。假设玛丽想卖掉一台她不再使用的电脑,而彼得想从她那里购买,但他们住在不同的州。玛丽在收到彼得的钱之前不会发货,而彼得在收到电脑并确认它符合他的预期之前不会付款。交易陷入了僵局(死锁)状态,因为彼得和玛丽都在等待对方先完成自己操作部分。
在执行不同的进程时,死锁会导致意外的行为和错误。然而,有一些技术可以避免死锁。
相关文章:
深入理解 GO 语言并发
1. 使用并发 在深入了解 Go 如何处理并发之前,先查看并发的概念。在计算机发展的早期阶段,计算机系统只有一个处理器负责执行所有指令。由于这种体系结构,计算机程序被编写成以串行的方式运行,在这种方式下,程序按照预定义的顺序逐个指令地执行。 随着计算机程序变得越来越…...

leetcode39组合总和
题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制重复被选…...

【JPCS独立出版,EI稳定检索】2024年工业机器人与先进制造技术国际学术会议(IRAMT 2024,9月27-29)
2024年工业机器人与先进制造技术国际学术会议(IRAMT 2024)将于2024年9月27-29日在中国成都举办。 此次会议将围绕工业机器人、机电技术、机械及制造等领域的最新研究成果展开讨论,并广泛邀请了国内外领域内的著名专家与学者。会议旨在搭建一个…...

Fal.ai Flux 1-Pro/Viva.ai/哩布哩布AI:AI绘图部分免费工具+原图提示词Prompt
目录 #1 找软件 #2 懂提示词 #3 更难的一步,会英文 我个人认为,想要玩文生图,你要会3个步骤: #1 找软件 主流文生图软件:Midjourney、Stable Diffusion、Dall-E 3 巧了,我用的都是小众、免费的画笔工…...
C++学习笔记----2、使用C++进行优雅编程(十)---- 格式化
许多人因为编程风格的问题被搞得焦头烂额,就因为对于在if中使用几个空格争论不休,导致友谊的小船说翻就翻。如果公司有相应的编程规范,只能说你比较幸运。因为有可能你不喜欢这些规范,但做为一个正常人来讲,至少有规范…...

双指针| Java | (hot100) 力扣283, 11, 15, 42做题总结
leetcode 11 盛最多水的容器 双层for循环暴力 超出时间限制 class Solution {public int maxArea(int[] height) {int h0;int v0;for(int i0; i<height.length; i) {for(int ji1; j<height.length; j) {h Math.min(height[i],height[j]);v Math.max(v, h*(j-i));}}…...
matlab求解方程
【MATLAB】求解含有三角函数的方程_matlab求解三角函数方程-CSDN博客 Matlab求解方程或函数的根,root,fzero,solve,fsolve的区别_matlab root-CSDN博客 非线性方程(组):MATLAB内置函数 solve, vpasolve, fsolve, fzero, roots [MATLAB] - GentleMin - …...

MySQL基础--视图,存储过程
介绍 视图是一种虚拟存在的表,视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。 通俗的讲,视图只保存了查询的 SQL 逻辑,不保存查询结果,所以我…...

学习记录第二十六天
进程运行 1,子进程和父进程做相同的事----创建子进程 执行任务 2,子进程做与父进程不同的事 ----fork exec exec族 l VS v :主要是第二个参数的传参方式不同 p :表示寻找可执行文件 是通过PATA环境变量 e : 表示可以给…...

Polars简明基础教程十一:可视化(一)
到本次讲座结束时,你将能够: 使用Polars的内部plot方法从Polars创建图表使用外部绘图库从Polars创建图表了解这些库如何支持Polars 通常,需要可视化库的最新版本来实现最大程度的兼容性 import polars as plimport hvplot as hv import ma…...

实战项目:贪吃蛇游戏的实现(上)
前言 Hello, 今天我们来一起完成一个实战项目:贪吃蛇。 相信大家都不会对这个游戏感到陌生,贪吃蛇游戏是久负盛名的游戏,他和俄罗斯方块,扫雷游戏等游戏位列世界经典游戏之列。这次我们旨在通过实战项目贪吃蛇的实现,…...

SHT30温湿度传感器全解析——概况,性能,MCU连接,样例代码
常见温湿度传感器测量范围:(价格仅供参考,具体性能要看折线图) 型号DHT11DHT20AHT10AHT20AHT30SHT20价格¥ 2.49¥3.04¥ 1.9¥1.4¥ 1.3¥5.5温度测量范围20—90%RH0—100%RH0—100%RH0—…...
SQL server 同环比计算模板
1、计算 月 年 季度的环比和同比 计算公式如下: 环比增长率 (本期数 - 上期数) / |上期数| 100% 同比增长率 (本期数 - 同期数) / |同期数| * 100% --- dbo.ads_erp_finance_gross_profit_actual_invoice_yoy_m…...
python发送外部请求
在Python中,服务器发送外部请求是一个常见的操作,尤其是在需要集成不同服务或API时。有多种库可以帮助你完成这项任务,但最流行和广泛使用的库之一是requests。以下是如何使用requests库在Python服务器中发送外部请求的基本步骤: …...
c++并发编程面试题
1. C中lock_guard和unique_lock的区别? 在C中,lock_guard和unique_lock都是用于管理互斥锁的类,它们提供了一种 RAII(Resource Acquisition Is Initialization)机制来确保锁在作用域结束时自动释放。尽管它们的目的相…...

K8S上安装LongHorn(分布式块存储) --use
要在 Kubernetes上安装 LongHorn,您可以按照以下步骤进行操作: 准备工作 参考 官网教程将LongHorn只部署在k8s-worker5节点上。https://github.com/longhorn/longhorn 安装要求 Each node in the Kubernetes cluster where Longhorn is installed must f…...
2024年前端技术发展趋势分析
2024年的前端技术发展趋势继续受到快速变化的技术环境和不断增长的用户期望的影响。以下是2024年前端技术发展的几个关键趋势: 1. Web 组件和自定义元素 Web 组件技术(包括 Shadow DOM、HTML Templates 和 Custom Elements)正在成为构建可重…...
spring boot 笔记大杂烩
一,springboot项目创建 springboot创建时idea会打开start.spring.io失败报错 可以手动打开这个页面,然后选择maven项目,然后修改group和name名然后添加依赖web,然后生成项目包,解压缩后用idea打开就能用了 运行后报错…...
如何在香港云服务器上优化网站性能?
在香港云服务器上优化网站性能可以通过以下几种方式进行,确保用户从全球各地访问时获得快速、稳定的体验: 1. 使用内容分发网络 (CDN) 优势:CDN可以将静态内容(如图像、视频、CSS、JavaScript文件)缓存到全球多个节点…...

STM32低功耗与备用备份区域
STM的备份备用区域其实就是两个区块:BKP和RTC。低功耗则其实是STM32四种模式中的三种耗能很低的模式。 目录 一:备用区域 1.BKP 2.RTC 二:低功耗模式 1.睡眠模式: 2.停机模式: 3.待机模式: 一&…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...