concurrency 并行编程

Goroutine

go语言的魅力所在,高并发。

线程是操作系统调度的一种执行路径,用于在处理器执行我们在函数中编写的代码。一个进程从一个线程开始,即主线程,当该线程终止时,进程终止。这是因为主线程是应用程序的原点。然后,主线程可以依次启动更多的线程,而这些线程可以启动更多的线程。

并发不是并行。并行是指两个或多个线程同时在不同的处理器执行代码。如果将运行时配置为使用多个逻辑处理器,则调度程序将在这些逻辑处理器之间分配 goroutine,这将导致 goroutine 在不同的操作系统线程上运行。但是,要获得真正的并行性,您需要在具有多个物理处理器的计算机上运行程序。否则,goroutine 将针对单个物理处理器并发运行,即使 Go 运行时使用多个逻辑处理器。

注意:① 空的 select{} 会永远进行 阻塞

② 如果当前的goroutine要执行但是需要等待另一个goroutine执行完毕才行,这时候就要把另一个goroutine的事情拿来自己做。

③ 使用goroutine考虑两个问题,一是它什么时候结束,二是你有没有一个方法让它结束

这里展示一个较好例子:

Memory model

go 的内存模型,个人总结:只要是多线程就不要觉得自己太聪明,使用”锁",确保操作事物的原子性,因为多线程之间的调度过程中,cpu,线程为了最大限度的性能,有可能改变不同线程之间关于整体事物的逻辑执行顺序,导致结果出现不可测性。指针copy的方法,指针是一个原子性,但是并不满足 single machine. 当然如果你只是单线程,那么这些忧虑不用考虑

为了说明读和写的必要条件,我们定义了先行发生(Happens Before)。如果事件 e1 发生在 e2 前,我们可以说 e2 发生在 e1 后。如果 e1不发生在 e2 前也不发生在 e2 后,我们就说 e1 和 e2 是并发的。
在单一的独立的 goroutine 中先行发生的顺序即是程序中表达的顺序。

  • 当下面条件满足时,对变量 v 的读操作 r 是被允许看到对 v 的写操作 w 的:
    • r 不先行发生于 w
    • 在 w 后 r 前没有对 v 的其他写操作
  • 为了保证对变量 v 的读操作 r 看到对 v 的写操作 w,要确保 w 是 r 允许看到的唯一写操作。即当下面条件满足时,r 被保证看到 w:
    • w 先行发生于 r
    • 其他对共享变量 v 的写操作要么在 w 前,要么在 r 后。


这一对条件比前面的条件更严格,需要没有其他写操作与 w 或 r 并发发生。

Package sync

data race : 线程竞争,在线程模型中Go 没有显式地使用锁来协调对共享数据的访问,而是鼓励使用 chan 在 goroutine 之间传递对数据的引用。这种方法确保在给定的时间只有一个 goroutine 可以访问数据。

go buid -race go test -race

i++是原子性操作吗? 不是,i++的底层是三行代码,并不是原子性。

Copy-On-Write 思路在微服务降级或者 local cache 场景中经常使用。写时复制指的是,写操作时候复制全量老数据到一个新的对象中,携带上本次新写的数据,之后利用原子替换(atomic.Value),更新调用者的变量。来完成无锁访问共享数据。这也是 Redis 进行写操作来更改数据的一种方法。

Mutex

  • go的几种 Mutex 锁的实现:
    • Barging. 这种模式是为了提高吞吐量,当锁被释放时,它会唤醒第一个等待者,然后把锁给第一个等待者或者给第一个请求锁的人。
    • Handsoff. 当锁释放时候,锁会一直持有直到第一个等待者准备好获取锁。它降低了吞吐量,因为锁被持有,即使另一个 goroutine 准备获取它。(一个互斥锁的 handsoff 会完美地平衡两个goroutine 之间的锁分配,但是会降低性能,因为它会迫使第一个 goroutine 等待锁。)
    • Spinning. 自旋在等待队列为空或者应用程序重度使用锁时效果不错。parking 和 unparking goroutines 有不低的性能成本开销,相比自旋来说要慢得多。

errgroup

实际生活中我们的errgroup使用的更多一些,用几个gooroutine 去进行分布处理业务,然后通过sync进行控制管理各个分支,把最后的数据再集合起来。 sync.waitGroup()

Chan

各个goroutine通过chan管道来进行实时通信。

channels 是一种类型安全的消息队列,充当两个 goroutine 之间的管道,将通过它同步的进行任意资源的交换。chan 控制 goroutines 交互的能力从而创建了 Go 同步机制。当创建的 chan 没有容量时,称为无缓冲通道。反过来,使用容量创建的 chan 称为缓冲通道。

无缓冲chan

ch := make(chan struct{})
无缓冲 chan 没有容量,因此进行任何交换前需要两个 goroutine 同时准备好。当 goroutine 试图将一个资源发送到一个无缓冲的通道并且没有goroutine 等待接收该资源时,该通道将锁住发送 goroutine 并使其等待。当 goroutine 尝试从无缓冲通道接收,并且没有 goroutine 等待发送资源时,该通道将锁住接收 goroutine 并使其等待。
意思就是双方都得准备好才能进行下去 , 无缓冲信道的本质是保证同步。

  • Receive 先于 Send 发生。
  • 好处: 100% 保证能收到。
  • 代价: 延迟时间未知。

有缓冲的chan

buffered channel 具有容量,因此其行为可能有点不同。当 goroutine 试图将资源发送到缓冲通道,而该通道已满时,该通道将锁住 goroutine并使其等待缓冲区可用。如果通道中有空间,发送可以立即进行,goroutine 可以继续。当goroutine 试图从缓冲通道接收数据,而缓冲通道为空时,该通道将锁住 goroutine 并使其等待资源被发送。

  • Send 先于 Receive 发生。
  • 好处: 延迟更小。
  • 代价: 不保证数据到达,越大的 buffer,越小的保障到达。buffer = 1 时,给你延迟一个消息的保障。

Context

context 的使用因该是贯穿全过程,而不是被把它放到一个对象结构体中去使用

context.WithValue() : 用于创建一个context对象

context.WithValue 方法允许上下文携带请求范围的数据。这些数据必须是安全的,以便多个 goroutine 同时使用。这里的数据,更多是面向请求的元数据,不应该作为函数的可选参数来使用(比如 context 里面挂了一个sql.Tx 对象,传递到 data 层使用),因为元数据相对函数参数更加是隐含的,面向请求的。而参数是更加显示的。

同一个 context 对象可以传递给在不同 goroutine 中运行的函数;上下文对于多个 goroutine 同时使用是安全的。对于值类型最容易犯错的地方,在于 context value 应该是 immutable 的,每次重新赋值应该是新的 context,即: context.WithValue(ctx, oldvalue)

比如 染色,API 重要性,Trace

注意选择使用 copy-on-write 的思路,解决跨多个 goroutine 使用数据、修改数据的场景。

COW: 从 ctx1 中获取 map1(可以理解为 v1 版本的 map 数据)。构建一个新的 map 对象 map2,复制所有 map1 数据,同时追加新的数据 “k2”: “v2” 键值对,使用 context.WithValue 创建新的 ctx2,ctx2 会传递到其他的 goroutine 中。这样各自读取的副本都是自己的数据,写行为追加的数据,在 ctx2 中也能完整读取到,同时也不会污染 ctx1 中的数据。

COW就是 copy-on-write

当一个 context 被取消时,从它派生的所有 context 也将被取消。WithCancel(ctx) 参数 ctx 认为是 parent ctx,在内部会进行一个传播关系链的关联。Done() 返回 一个 chan,当我们取消某个parent context, 实际上上会递归层层 cancel 掉自己的 child context 的 done chan 从而让整个调用链中所有监听 cancel 的 goroutine 退出。

如果要实现一个超时控制,通过上面的 context 的 parent/child 机制,其实我们只需要启动一个定时器,然后在超时的时候,直接将当前的 context 给 cancel 掉,就可以实现监听在当前和下层的额 context.Done() 的 goroutine 的退出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/16030.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

红黑树封装map和set

红黑树源代码 我们将由下列的KV模型红黑树来模拟封装STL库中的map和set 注意&#xff1a;为了实现封装map和set&#xff0c;我们需要对下列源码进行优化。 #pragma once #include<iostream> using namespace std; //枚举类型的颜色分类 enum Colour {RED,BLACK };//定…

Markdown魔法手册:解锁高效写作的新技能

边使用边更新0.0... 文章目录 一、如何在Markdown中插入表情&#xff1f;二、文字样式设置1.文本颜色设置2.文本字号设置3.文本字体设置4. 实战演练5.黄色高亮 一、如何在Markdown中插入表情&#xff1f; 在Markdown中插入表情&#xff08;emoji&#xff09;的方法取决于你使用…

如何提升百度小程序的收录?百度小程序如何做优化?

​ 如何通过百度小程序获得更多的自然流量&#xff1f;这是做百度小程序肯定要考虑的问题&#xff0c;做百度小程序的目的就是想借助百度生态&#xff0c;做相应的关键词给自己的小程序引流&#xff0c;如何把流量给做起来呢&#xff0c;接下来我从不同的方面给大家进行分析讲解…

最新ChatGpt Desktop for Mac 安装使用教程

1. 下载地址 请点击链接下载 ChatGPT Desktop for MacOS 2. 使用要求 MacOS 版本 14需要时M1芯片的&#xff0c;如果你是因特尔的暂时还还不行 就算下载了也会出现下面的异常 3. 获取权限资格 目前 ChatGPT MacOS Desktop还不是全量开放的, 如果你没有收到通知说明你还没…

ipa 覆盖算法测试

相关文章 ipa 功能包测试 ipa 分区算法 ipa 分区算法总结&#xff0c;部分算法图解 ipa 覆盖算法分析&#xff08;一&#xff09; ipa 覆盖算法分析&#xff08;二&#xff09; 测试 网上找的地图&#xff1a; fig.1 测试地图 opencv fig.2 opencv 显示的覆盖路径 rviz fi…

6.定时器分时复用测量占空比

1.CUBEMAX配置 测量PA6&#xff0c;PA7输出的占空比&#xff0c;只需要把主要的配置&#xff0c;配置为A6口就行&#xff0c;A7口黄色表示配置不正确&#xff0c;不用管。 2.软件代码 TIME.c中找到TIM3的初始化&#xff0c;在后面初始化A7口 void MX_TIM3_Init_PA7(void) {/*…

创新实训2024.05.25日志:Web应用技术选型

我们的web应用使用python web的fastapi框架&#xff0c;通过uvicorn开启web服务。 1. refs 官网文档&#xff1a;FastAPI (tiangolo.com) github&#xff1a;https://github.com/tiangolo/fastapi 2. 环境配置 python:3.11 uvicorn:0.29.0 pip install "uvicorn[stan…

老外卖27刀每月的教程已经更新

用了两天半的时间&#xff0c;边学习&#xff0c;边整理了一份老外的视频教程&#xff0c;涉及Facebook&#xff0c;YouTube&#xff0c;tiktok等大的流量平台&#xff0c;有案例&#xff0c;有分析&#xff0c;有如何做。 这个教程是老外讲的&#xff0c;没有什么玄乎的塑造价…

聊聊ChatGPT的本质

这是鼎叔的第九十八篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。 阶段性总结下我对ChatGPT的基础理解&#xff0c;算是一篇学习思考笔记吧。其中难免有很多不准确的&#xff0c;或过于简略的地方&#xff0c;将来再迭代学习。 OpenAI做ChatGPT的底层逻辑…

如何利用线程池实现互联网验证码保护服务

如何利用线程池实现互联网验证码保护服务 1、业务背景与实现思路2、代码实操1、业务背景与实现思路 首先介绍一下业务背景,假设我们的系统是一个短视频播放网站,每个新加入的用户都需要注册账号并绑定手机号。为了验证用户手机的正确性,我们的系统会发送一条验证码到用户注…

K8s的kubectl的基本操作

K8s的kubectl的基本操作 K8s基本信息的查看 查看版本信息 kubectl versio查看资源对象简写 kubectl api-resources查看集群信息 kubectl cluster-info配置kubectl自动补全 source <(kubectl completion bash)查看master节点状态 kubectl get cs查看命名空间 kubectl…

【找出第 K 大的异或坐标值】python

4层循环暴力超时 class Solution:def kthLargestValue(self, matrix: List[List[int]], k: int) -> int:nums[]for a in range(len(matrix)):for b in range(len(matrix[0])):num0for i in range(a1):for j in range(b1):num^matrix[i][j]nums.append(num)nums.sort()retu…

类的内存对齐位段位图布隆过滤器哈希切割一致性哈希

文章目录 一、类的内存对齐1.1规则1.2原因 二、位段2.1介绍2.2内存分配问题2.3跨平台问题2.4使用的注意事项 三、位图的应用3.1 给40亿个不重复的无符号整数&#xff0c;找给定的一个数。&#xff08;int的范围可以到达42亿多&#xff09;3.2 给定100亿个整数&#xff0c;设计算…

Golang实现文件复制

方法&#xff1a;三种 package zdpgo_fileimport ("errors""io""os" )// CopyFile 使用io.Copy进行文件的复制&#xff0c;同时也会复制文件的所有权限 // param src 复制文件 // param des 目标文件 // return error 错误信息 func CopyFile(s…

2024年弘连网络FIC大会竞赛题线下决赛题

总结&#xff1a; FIC决赛的时候&#xff0c;很多小问题没发现&#xff0c;在pve平台做题确实很方便。 这套题目复盘完&#xff0c;服务器这块的知识确实收获了很多&#xff0c;对pve集群平台和网络拓扑也有了一定的认识&#xff0c;感谢各位大佬悉心指导。 接下来&#xff0…

【FPGA】Verilog:奇校验位生成器的实现(Odd Parity bit generator)

解释奇数奇偶校验位生成器和检查器的仿真结果及过程。 真值表和卡洛图: Odd Parity Bit Generator A B C

怎么在pyqt中显示matplotlib的绘图?

想要在pyqt中显示matplotlib的绘图&#xff0c;在绘图时&#xff0c;其实不必使用以下语句&#xff1a; matplotlib.use("Qt5Agg") # 声明使用QT5最关键的语句是&#xff1a; from matplotlib.backends.backend_qt5agg import FigureCanvasQTAggFigureCanvasQTAgg…

学 Python 具体能干什么?

Python 是一种功能强大、用途广泛的编程语言&#xff0c;因其简洁易读的语法和丰富的库生态系统而备受欢迎。学习 Python后&#xff0c;你可以从事以下几方面的工作&#xff1a; 1. Web 开发 Python 有很多流行的 Web 框架&#xff0c;如&#xff1a; Django&#xff1a;一个…

Android studio的Gradle出问题

Gradle sync failed: Plugin [id: com.android.application, version: 7.1.1, apply: false] was not found in any of the following sources: 在src里面的build.gradle中 plugins { id ‘com.android.application’ } 的上面加上 buildscript {repositories {jcenter()}depen…

从 0 开始实现一个网页聊天室 (小型项目)

实现功能 用户注册和登录好友列表展示会话列表展示: 显示当前正在进行哪些会话 (单聊 / 群聊) , 选中好友列表中的某个好友, 会生成对应的会话实时通信, A给B发送消息, B的聊天界面 / 会话界面能立刻显示新的消息 TODO: 添加好友功能用户头像显示传输图片 / 表情包历史消息搜…