go并发编程(中)

目录

一、并发安全性

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.mfbz.cn/a/215132.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络层之IP数据报格式、数据报分片、IPv4、子网划分和子网掩码

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

openmmlab环境搭建及模拟kitti数据集跑pointpillars模型

点云训练—openmmlab环境搭建及模拟kitti数据集跑pointpillars模型 1 环境搭建 在我的 linux 服务器上&#xff0c;基于ubuntu20.04 参见&#xff1a;开始你的第一步 — MMDetection3D 1.3.0 文档 1.1 本地环境已安装anaconda. anaconda的安装参见博文&#xff1a;DS6.1-Y…

Linux 基本语句_14_信号灯实验

原理&#xff1a; Send进程通过建立共享内存区域&#xff0c;并向其中写入数据&#xff0c;Recive通过与共享内存连接读取其中的数据。 但是如果进程进行读取操作的时候其他进程再次写入会产生数据丢失&#xff0c;产生竞态&#xff0c;为了确保在某段时间内只有一个操作&…

Leetcode—1038.从二叉搜索树到更大和树【中等】

2023每日刷题&#xff08;四十九&#xff09; Leetcode—1038.从二叉搜索树到更大和树 算法思想 二叉搜索树的中序遍历&#xff08;左根右&#xff09;结果是一个单调递增的有序序列&#xff0c;我们反序进行中序遍历&#xff08;右根左&#xff09;&#xff0c;即可以得到一…

基于Java SSM框架实现母婴儿用品网站系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现母婴儿用品网站系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 母婴用品网站&#xff0c;主要的模块包括管理员&#xff1b;主页、个人中心、用户管理、商品分…

wireshark自定义协议插件开发

目录 脚本代码 报文显示 脚本代码 local NAME "test" test_proto Proto("test", "test Protocol") task_id ProtoField.uint16("test.task_id", "test id", base.DEC) cn ProtoField.uint8("test.cn", &qu…

数学建模-数据新动能驱动中国经济增长的统计研究-基于数字产业化和产业数字化的经济贡献测度

数据新动能驱动中国经济增长的统计研究-基于数字产业化和产业数字化的经济贡献测度 整体求解过程概述(摘要) 伴随着数据要素化进程的不断加深&#xff0c;对于数据如何作用于经济发展&#xff0c;数据与其他要素结合产生的动能应该如何测度的研究愈发重要。本文将数据新动能分…

最热门超声波清洗机有哪些?热门超声波清洗机推荐

眼镜党朋友第一次接触超声波清洗机应该是在眼镜店的时候&#xff0c;把眼镜拿给老板他几分钟就搞定眼镜清洗的&#xff0c;是的没有错&#xff0c;那个机器叫超声波清洗机&#xff0c;不需要自己动手就可把眼镜清洗干净的一款智能清洁工具&#xff0c;它的出现可以说是方便了我…

计算机网络扫盲(4)——时延

一、概述 在这里&#xff0c;我们考虑分组交换网的情况&#xff0c;因特网可以被看成是一种基础设施&#xff0c;该基础设施为运行在端系统上的分布式应用提供服务。在理想情况下&#xff0c;我们希望因特网服务能够在任意两个端系统之间随心所欲地移动数据而没有任何数据地丢失…

软信天成:数据泄露日趋严重 “资产”保护何去何从

随着数据应用的逐渐深入&#xff0c;越来越多的企业意识到&#xff1a;数据作为信息的载体&#xff0c;可以成为企业知识产权、收益流和具备竞争优势的基础资产。然而&#xff0c;当包含大量敏感信息的数据被视作资产时&#xff0c;亦将直面信息被“窃取”、“泄露”和“滥用”…

CrapApi部署手册( maven+tomcat+idea)

目录 一、本章节所用到的资源共享&#xff0c;嫌麻烦的可以直接下载本地配置好运行使用二、idea maven tomcat启动&#xff0c;我的maven和tomcat的配置三、遇到的问题四、项目运行后效果图转载请标明出处&#xff0c;写作不易如果有用请给个赞~~~~~~~~~~~~~~~~~~~~~~~~~~~~~…

跨网文件摆渡系统:安全、可控的数字传输桥梁

在企业高度信息化的时代&#xff0c;数据的流通与共享已经成为企业、组织乃至个人之间不可或缺的沟通方式。然而&#xff0c;在数据流通的过程中&#xff0c;我们经常会遇到各种难题和挑战&#xff0c;尤其是当涉及到不同网络环境之间的文件传输。这不仅需要保证文件的安全性&a…

基于Java SSM框架实现人才小区公寓社区物业管理系统项目【项目源码+论文说明】

基于java的SSM框架实现人才小区公寓社区物业管理系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个人才公寓管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff…

MySQL练习题,学生成绩查询练习题,附带答案

题目 (一) 新建以下几个表 student(学生表)&#xff1a; snosnamesexdeptbirthagePhone 其中约束如下&#xff1a; &#xff08;1&#xff09; 学号不能存在相同的 sno int auto_increment primary key &#xff08;2&#xff09; 名字为非空 sname varchar(20) not nu…

Excel如何设置在未打印时显示虚线打印时不显示虚线

记得之前分享过一个BOM表模板&#xff0c;但是在我打印时&#xff0c;发现明明是留空白的地方却打印出来的虚线 后来&#xff0c;看了自己的页面布局&#xff0c;原来是网格线设置错误了 当我设置为查看时显示网格线&#xff0c;打印时不显示网格线&#xff0c;这样就正常了

二百一十、Hive——Flume采集的JSON数据文件写入Hive的ODS层表后字段的数据残缺

一、目的 在用Flume把Kafka的数据采集写入Hive的ODS层表的HDFS文件路径后&#xff0c;发现HDFS文件中没问题&#xff0c;但是ODS层表中字段的数据却有问题&#xff0c;字段中的JSON数据不全 二、Hive处理JSON数据方式 &#xff08;一&#xff09;将Flume采集Kafka的JSON数据…

maven篇---第二篇

系列文章目录 文章目录 系列文章目录前言一、什么是Maven的坐标?二、讲一下maven的生命周期三、说说你熟悉哪些maven命令?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的…

C# OpenVINO 模型信息查看工具

目录 效果 支持模型 项目 代码 下载 C# OpenVINO 模型信息查看工具 效果 支持模型 ONNX format (*.onnx) PDPD (*.pdmodel) TF (*.pb) TFLite (*.tflite) 项目 代码 using Sdcb.OpenVINO; using System; using System.Collections.Generic; using System.Text; using…

怎么理解回流和重绘?

回流&#xff08;reflow&#xff09;和 重绘&#xff08;repaint&#xff09;是浏览器渲染过程中的两个关键概念。 一、概念&#xff1a; 回流指的是浏览器在计算文档流布局&#xff08;layout&#xff09;时&#xff0c;重新计算元素的位置和大小的过程。当页面中的元素发生尺…

spring boot 事件机制

目录 概述实践监听spring boot ready事件代码 源码初始化流程调用流程 结束 概述 spring boot 版本为 2.7.17 。 整体看一下spring及spring boot 相关事件。 根据下文所给的源码关键处&#xff0c;打上断点&#xff0c;可以进行快速调试。降低源码阅读难度。 实践 spring…