go并发编程(中)

news2025/4/6 17:06:55

目录

一、并发安全性

1.1  变量并发安全性

1.2 容器并发安全性

二、多路复用

三、协程常见的面试题

3.1交替打印奇数偶数


一、并发安全性

1.1  变量并发安全性

这个和C++中并发安全是一样的,主要是多个线程对临界资源的同时访问,最经典的就是 n++操作,因为这一步并不是原子操作的。

这里我们可以用到 atomic(原子操作,让n++变成一步),也可也使用加锁的办法

我们先来模拟一下错误的操作:这里我们开1000个协程,都执行 n++的操作

package main

import (
	"fmt"
	"sync"
)

var n int //n

func main() {
	wg := sync.WaitGroup{}
	wg.Add(1000)
	for i := 0; i < 1000; i++ {
		go func() {
			defer wg.Done()
			n++
		}()
	}
	wg.Wait()
	fmt.Println(n)
}

我们运行一下:

明显可以看到结果不是1000,这就是并发不安全的

1.  使用atomic

2. 用读写锁实现

1.2 容器并发安全性

读写一般的map是不可以的,我们需要用到sync.Map  ,  存数据是 mp.store( i , i ), 读数据是 mp.lode(i)

二、多路复用

我们都知道,当前的IO多路复用有三种: select 、poll、epoll  ,在go语言当中,只有select(这里是针对不同的操作系统进行了封装,我们也不用考虑到底是什么,只管用就行了)

go的select在遍历的时候是只要有一个准备好了就会返回

// 倒计时  模拟火箭发射
func countDown(countCh chan int, n int, finishCh chan struct{}) {
	if n <= 0 { //从n开始倒数
		return
	}
	for {
		countCh <- n //把n放入管道
        time.sleep(time.second)  //等待一秒
		n--          //n减1
		if n <= 0 {  //n减到0时退出
		    finishCh <- struct{}{} //成功结束
			break                  //退出for循环
		}
	}
}

// 中止  键盘有输入就表示要中断
func abort(ch chan struct{}) {
	buffer := make([]byte, 1)
	os.Stdin.Read(buffer) //阻塞式IO,如果标准输入里没数据,该行一直阻塞。注意在键盘上敲完后要按下Enter才会把输入发给Stdin
	ch <- struct{}{}
}

func main() {
	countCh := make(chan int)
	finishCh := make(chan struct{})
	go countDown(countCh, 10, finishCh) //开一个子协程,去往countCh和finishCh里放数据
	abortCh := make(chan struct{})
	go abort(abortCh) //开一个子协程,去往abortCh里放数据

LOOP:
	for { //循环监听
		select { //同时监听3个channel,谁先准备好就执行谁,然后进入下一次for循环
		case n := <-countCh:
			fmt.Println(n)
		case <-finishCh:
			fmt.Println("finish")
			break LOOP //退出for循环。在使用for select时,单独一个break不能退出for循环
		case <-abortCh:
			fmt.Println("abort")
			break LOOP //退出for循环
		}
	}
}

三、协程常见的面试题

3.1交替打印奇数偶数

方法一:使用无缓存的channel 进行通信

// PrintOddAndEven1 /*
func PrintOddAndEven1() {
	//方法一,使用无缓冲的channel进行通信
	var wg = new(sync.WaitGroup) //注意这里需要是指针go语言当中都是值传递
	wg.Add(2)
	ch := make(chan struct{}) //无缓冲channel
	defer close(ch)
	maxVal := 100
	go func() {
		defer wg.Done()
		for i := 1; i <= maxVal; i++ {
			ch <- struct{}{}
			if i%2 == 1 { //奇数
				fmt.Printf("the odd is %d\n", i)

			}
		}
	}()

	go func() {
		defer wg.Done()
		for i := 1; i <= maxVal; i++ {
			<-ch          //从管道当中读取一个数据
			if i%2 == 0 { //偶数
				fmt.Printf("the even is %d\n", i)

			}
		}
	}()
	wg.Wait()

}
func main() {
	PrintOddAndEven1()
	fmt.Println("over")
}

/*

原理因为c1是无缓存的,所以只有当读写同时就绪才不会被阻塞,当同时就绪的时候,两个协程会同时进入if条件语句,他们的i值都是一样的,这时候只有一个是满足条件的,所以会按顺序交替打印出 1~100.

方法二:使用有缓存的channel进行通信

// 方法二:用有缓存的channel进行通信
func HaveCach() {
	wg := sync.WaitGroup{}
	wg.Add(2)

	c1 := make(chan int, 1)
	c2 := make(chan int, 1)

	defer close(c1)
	defer close(c2)
	c1 <- 1 //先往c1当中写入一个数据,确保先打印奇数

	go func() {
		defer wg.Done()
		for i := 1; i < 50; i += 2 {
			<-c1
			fmt.Printf("奇数 :%d\n", i)
			c2 <- 1 //通知c2
		}
	}()
	go func() {
		defer wg.Done()
		for i := 2; i < 50; i += 2 {
			<-c2
			fmt.Printf("偶数 :%d\n", i)
			c1 <- 1 //通知c1
		}
	}()
	wg.Wait()
}

func main() {
	HaveCach()
	fmt.Println("over")
}

第二个方法使用这个有缓冲的channel。有缓冲的channel当容量没有达到上限时写入不会阻塞在这里奇数协程的channel容量为1我们提前给他写入了一个数据因此当偶数和奇数协程都开始读取数据时,首先读取到数据的是奇数协程,奇数协程打印完之后在通知偶数协程打印,偶数协程打印完成之后在通知奇数协程重复下去就实现了交替打印的效果。

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

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

相关文章

MQ - 消息系统

消息系统 1、消息系统的演变 在大型系统中&#xff0c;会需要和很多子系统做交互&#xff0c;也需要消息传递&#xff0c;在诸如此类系统中&#xff0c;你会找到源系统&#xff08;消息发送方&#xff09;和 目的系统&#xff08;消息接收方&#xff09;。为了在这样的消息系…

Java 连接数据库

数据库&#xff1a;存储数据&#xff08;集中管理&#xff09; 目的&#xff1a; 文件中的数据能够放在数据库中集中管理 管理方法&#xff1a;一个项目一个库&#xff0c;每个库中包含最小化数据的表 开发&#xff1a; 节省存储空间&#xff0c;节省运行空间&#xff0c;采…

【富文本编辑器】原生JS使用WangEditor和vue上传图片前后端demo

【富文本编辑器】原生JS使用WangEditor上传图片前后端demo 第一步 HTML 第二步 初始化WangEditor与图片上传回调函数 第三步 后端返回数据体封装 第四步 后端接口上传图片&#xff0c;并返回图片地址 最近&#xff0c;我遇到了这样一个问题&#xff1a;因为我们的项目是基于…

SDGAN:一种用于低剂量CT图像重建的新型空间可变形生成对抗性网络

SDGAN: A novel spatial deformable generative adversarial network for low-dose CT image reconstruction SDGAN&#xff1a;一种用于低剂量CT图像重建的新型空间可变形生成对抗性网络背景贡献实验方法The conformer-based generatorThe dual-scale discriminatorThe spatia…

C/S与B/S的区别

B/S与C/S理解 C/S结构B/S结构问题数据放在服务器端与客户端的利弊 C/S结构 客户端&#xff1a;用户安装的软件 服务端&#xff1a;统一管理数据库的主机中的软件 叫做服务端。 B/S结构 用户通过浏览器实现&#xff08;往往表示业务逻辑在前端进行实现&#xff0c;主要业务逻…

栈和队列的OJ题——14.用栈实现队列

14.用栈实现队列 232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; /* 解题思路&#xff1a; 此题可以用两个栈实现&#xff0c;一个栈进行入队操作&#xff0c;另一个栈进行出队操作 出队操作&#xff1a; 当出队的栈不为空是&#xff0c;直接进行出栈操作&#xff…

基于SSM的网上手机销售系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

OpenSSH(CVE-2023-38408)OpenSsh9.5一键升级修复

yum install -y git cd /root git clone https://gitee.com/qqmiller/openssh-9.5p1-.x86_64.git cd openssh-9.5p1-.x86_64/ bash openssh_update.sh重启sshd&#xff1a; systemctl restart sshd 查看sshd状态&#xff1a; systemctl status sshd 重要的是按此操作升级完成…

一文彻底弄懂动态规划【DP】

动态规划是一种重要的算法&#xff0c;它能解决很多看似复杂的问题&#xff0c;关键在于找到问题的子问题结构&#xff0c;并根据子问题的解决方式来解决原问题。首先要了解的是动态规划的基本思想&#xff1a; 动态规划的基本思想是&#xff1a;将一个复杂的问题分解为一系列…

SpringBootAdmin

SpringBootAdmin 文章目录 SpringBootAdmin创建SpringBootAdmin服务端创建SpringBootAdmin客户端启动应用 总结 github地址 https://github.com/codecentric/spring-boot-admin 可以查到所有的版本号 创建SpringBootAdmin服务端 创建springBoot项目的时候&#xff0c;在ops选项…

图文并茂教你模拟302接口,实现js中axios,fetch遇到302状态码后跳转的多种方案axios,fetch成功响应拦截302

前情提要 日常工作中&#xff0c;我们会使用fetch,或者axios发起请求来获取数据&#xff0c;但是当我们遇到一些特殊需求的时候&#xff0c;使用不同库之后&#xff0c;会得到不同的结果&#xff0c;例如302,308的状态码&#xff0c;那么我们应该怎么处理这两种情况呢&#xf…

【Linux】第二十六站:软硬链接

文章目录 一、软链接二、硬链接三、ln命令四、该如何理解硬链接&#xff1f;五、如何理解软链接六、为什么要用软硬链接1.软链接的应用场景2.硬链接的应用场景 一、软链接 如下所示&#xff0c;我们创建一个文件以后&#xff0c;然后执行下面的指令 ln -s file.txt soft-link…

Prime 2.0

信息收集 # Nmap 7.94 scan initiated Thu Nov 23 20:09:06 2023 as: nmap -sn -oN live.nmap 192.168.182.0/24 Nmap scan report for 192.168.182.1 Host is up (0.00018s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap scan report for 192.168.182.2 Host is u…

P-Tuning v2论文概述

P-Tuning v2论文概述 P-Tuning v2论文概述前言微调的限制性P-Tuning的缺陷P-Tuning v2 摘要论文十问NLU任务优化点实验数据集预训练模型实验结果消融实验 结论 P-Tuning v2论文概述 前言 微调的限制性 微调&#xff08;fine-tuning&#xff09;是一种在预训练模型基础上进行目…

使用 Kettle 完成数据 ETL

文章目录 使用 Kettle 完成数据 ETL数据清洗数据处理 使用 Kettle 完成数据 ETL 现在我们有一份网站的日志数据集&#xff0c;准备使用Kettle进行数据ETL。先将数据集加载到Hadoop集群中&#xff0c;然后对数据进行清洗&#xff0c;最后加载到Hive中。 在本地新建一个数据集文…

Active Stereo Without Pattern Projector论文精读

1.背景补充 主动立体相机和被动立体相机的主要区别在于它们获取立体视觉信息的方式 主动立体相机12&#xff1a; 主动立体视觉是指寻找最佳的视角去重建目标或者场景1。主动视觉的实现方式通常有&#xff1a;改变环境中的光照条件、改变相机的视角、移动相机自身位置等&…

大模型中幂律缩放法则和涌现能力

幂律缩放法则是一种用于描述两个变量之间关系的数学模型。 根据幂律缩放法则&#xff0c;当一个变量的值变化时&#xff0c;另一个变量的值以指数方式变化。具体而言&#xff0c;幂律缩放法则可以表示为Y a * X^b&#xff0c;其中Y表示一个变量的值&#xff0c;X表示另一个变…

国民技术N32_MCU ADC如何获取高精度采样数据

前言 国民技术微控制器内置最多四个高级 12 位 ADC (取决于产品系列) &#xff0c;具有校准功能&#xff0c;用于提高环境条件 变化时的 ADC 精度。 在涉及模数转换的应用中&#xff0c; ADC 精度会影响整体的系统质量和效率。为了提高此精度&#xff0c;必须了解与 ADC 相关…

鸿蒙开发学习笔记

快速入门 配置网络权限 1.打开项目的 module.json5 文件 2.在module 里面写下面代码 3.这样就可以使用网络图片了 4.模拟器上就可以正常显示网络图片了 5.官方文档有相关说明 6. 华为官方编辑工具使用技巧&#xff08;内置文档&#xff09;&#xff0c;鼠标移动到标签上&…

JVM内存结构:StringTable与常量池关系

首先看一道题 这就涉及到StringTable和常量池&#xff0c;答案在文末&#xff0c;全做对就不用看了 而StringTable的位置在不同版本也有变化 &#xff0c; 我们只探讨jdk1.8版本 与StringTable 串池对应的是常量池 案例一、常量池和串池联系 引用所指肯定不会是常量池中的字…