10.Go-goroutine,waitgroup,互斥锁,channel和select
10.1.goroutine
goroutine的使用
//Learn_Go/main.go
package main import (
"fmt"
"time"
) func demo(count int) {
for i :=1; i < 10; i++{
fmt.Println(count,":",i)
}
} func main() {
for i :=1; i < 10; i++{
go demo(i)
}
//添加休眠时间等待goroutine执行结束
time.Sleep(3e9)
}
10.2.waitgroup
WaitGroup直译为等待组,其实就是计数器,只要计数器中有内容将一直阻塞
WaitGroup有三种方法
- Add(delta int)表示向内部计数器添加增量(delta),其中参数delta可以使负数
- Done() 表示减少waitgroup计数器的值,应当在程序最后执行,相当于Add(-1)
- Wait() 表示阻塞知道waitgroup计数器为0
//Learn_Go/main.go
package main import (
"fmt"
"sync"
) func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++{
go func(j int) {
fmt.Println("第",j,"次执行")
wg.Done()
}(i)
}
wg.Wait()
fmt.Println("程序结束")
}
10.3.互斥锁和读写锁
(1)互斥锁
可以使用sync.Mutex对内容加锁,互斥锁的使用场景
- 多个gouroutine访问同一个函数代码段
- 操作一个全局变量
- 为了保证共享变量安全性,值安全性
(2)读写锁
Go语言中的map不是线程安全的,多个gouroutine同时操作会出现错误
RWMutex可以添加多个读锁或者一个写锁,读写锁不能同时存在
map在并发下读写就需要结合读写锁完成
互斥锁表示锁的代码同一时间只能有一个goroutine运行,而读写锁表示在锁范围内数据的读写操作
//Learn_Go/main.go
package main import (
"fmt"
"sync"
) func main() {
var rwm sync.RWMutex
var wg sync.WaitGroup
wg.Add(10)
m := make(map[int]int)
for i := 0; i < 10; i++{
go func(j int) {
rwm.Lock()
m[j] = j
fmt.Println(m)
rwm.Unlock()
wg.Done()
}(i)
}
wg.Wait()
fmt.Println("程序结束")
}
10.4.channel
channel是进程内通信方式,每个channel只能传递一个类型的值,这个类型需要在声明channel时指定
channel在Go中主要的两个作用:同步和通信
(1)声明channel的语法
- var 名称 chan 类型
- var 名称 chan <- 类型 只写
- var 名称 <- chan 类型 只读
- 名称 := make(chan int) 无缓存chanel
- 名称 := make(chan int) 无缓存channel
- 名称 := make(chan int,100) 有缓存channel
(2)操作channel的语法
- ch <- 值 向ch中添加一个值
- <- ch 从ch中取出一个值
- a := <-ch 从ch中取出一个值并赋值给a
- a,b := <-ch 从ch中取出一个值赋值给a,如果ch已经关闭或ch中没有值,b为false,
(3)无论是向channel存数据还是取数据都会阻塞
//Learn_Go/main.go
package main import "fmt" func main() {
ch := make(chan int)
go func() {
fmt.Println("执行")
ch <- 111
}()
a := <- ch
fmt.Println(a)
fmt.Println("程序结束")
}
(4)使用channel实现gouroutine之间通信
//Learn_Go/main.go
package main import "fmt" func main() {
ch1 := make(chan string)
ch2 := make(chan int) go func() {
ch1 <- "derek"
ch2 <- 111
}() go func() {
content := <- ch1
fmt.Println("取出数据:",content) //取出数据: derek
ch2 <- 222
}() a := <- ch2
b := <- ch2
fmt.Println(a,b) //111 222
fmt.Println("程序结束")
}
(5)可以使用for range获取channel中内容
//Learn_Go/main.go
package main import "fmt" func main() {
ch1 := make(chan int)
ch2 := make(chan int) go func() {
for i := 0; i<10;i++{
ch1 <- i
}
ch2 <- 222
}() go func() {
for n := range ch1{
fmt.Println(n)
}
}()
<- ch2
fmt.Println("程序结束")
}
10.5.select
select执行过程
- 每个case必须是一个IO操作
- 哪个case可以执行就执行哪个
- 所有case都不能执行时,执行default
- 所有case都不能执行且没有default,将会阻塞
//Learn_Go/main.go
package main import "fmt" func main() {
ch1 := make(chan int,2) //有缓存的channel
ch2 := make(chan int,3)
ch1 <- 111
ch2 <- 222
select {
case a := <-ch1:
fmt.Println(a)
case b := <-ch2:
fmt.Println(b)
default:
fmt.Println("错误")
}
}
select多和for循环结合使用
//Learn_Go/main.go
package main import "fmt" func main() {
ch := make(chan int)
for i := 0; i < 10;i++{
go func(j int) {
ch <- j
}(i)
}
//用for循环一直接受
for {
select {
case a := <- ch:
fmt.Println(a)
default:
}
}
}
10.Go-goroutine,waitgroup,互斥锁,channel和select的更多相关文章
- 10.Go-goroutine,waitgroup,互斥锁和channel
10.1.goroutine goroutine的使用 //Learn_Go/main.go package main import ( "fmt" "time" ...
- liteos互斥锁(七)
1. 概述 1.1 基本概念 互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理. 任意时刻互斥锁的状态只有两种,开锁或闭锁.当有任务持有时,互斥锁处于闭锁状态,这个任务 ...
- 多图详解Go的互斥锁Mutex
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码时14.4 Mutex介绍 Mutex 结构体包含两个字段: 字段s ...
- 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 百篇博客分析OpenHarmony源码 | v27.02
百篇博客系列篇.本篇为: v27.xx 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁当立贞 ...
- goroutiine同步/channel、互斥锁、读写锁、死锁/条件变量
1. Goroutine同步[数据同步] 为什么需要goroutine同步 gorotine同步概念.以及同步的几种方式 1.1 为什么需要goroutine同步 package main impor ...
- Go基础系列:互斥锁Mutex和读写锁RWMutex用法详述
sync.Mutex Go中使用sync.Mutex类型实现mutex(排他锁.互斥锁).在源代码的sync/mutex.go文件中,有如下定义: // A Mutex is a mutual exc ...
- Go语言基础之13--线程安全及互斥锁和读写锁
一.线程安全介绍 1.1 现实例子 A. 多个goroutine同时操作一个资源,这个资源又叫临界区 B. 现实生活中的十字路口,通过红路灯实现线程安全 C. 火车上的厕所(进去之后先加锁,在上厕所, ...
- Go同步等待组/互斥锁/读写锁
1. 临界资源 package main import ( "fmt" "time" ) func main() { /* 临界资源: */ a := 1 go ...
- Go语言中的互斥锁和读写锁(Mutex和RWMutex)
目录 一.Mutex(互斥锁) 不加锁示例 加锁示例 二.RWMutex(读写锁) 并发读示例 并发读写示例 三.死锁场景 1.Lock/Unlock不是成对出现 2.锁被拷贝使用 3.循环等待 虽然 ...
随机推荐
- Linux0.11之进程0创建进程1(1)
进程0是由linus写在操作系统文件中的,是预先写死了的.那么进程0以后的进程是如何创建的呢?本篇文章主要讲述进程0创建进程1的过程. 在创建之前,操作系统先是进行了一系列的初始化,分别为设备号.块号 ...
- list 属性字段直接转成字符串数组
List<Car> cars = //whatever; string concat = String.Join(",", cars.Select(c => c. ...
- 对js原型对象、实例化对象及prototype属性的一些见解
什么是原型对象? 请看下面的代码,我们以各种姿势,创建了几个方法! function fn1() { } var fn2 = function () { } var fn3 = new Functio ...
- 浅谈TCP扫描与SYN扫描与FIN扫描
下面就这三种方法来小小的探讨一下,不对的地方还请多多指教! 1:TCP扫描 相对来说是速度比较慢的一种,为什么会慢呢?因为这种方法在扫描的时候会从本地主机的一个端口向目标主机的一个端口发出一个连接请求 ...
- Emgu 学习(2) 视频文件播放
播放AVI视频文件 static void Main(string[] args) { CvInvoke.NamedWindow("TestVideo", NamedWindowT ...
- CDH目录
配置文件都在:/etc/服务名, 看hadoop的classpath |grep conf /etc/hadoop/conf log都在: /var/log/服务名 看scm的log: tail -1 ...
- 关于Java中excel表格导出的总结(Java程序导出模板和Java根据模板导出表格两种实现方式)
导出excel通用模板(程序定义模板导出) 转载原文:https://www.jianshu.com/p/5c7b359a159c 如下代码,本方法主要用于程序定义模板格式,并导出文件.该方法将定义和 ...
- 小菜鸟之java异常
一.异常简介 什么是异常? 异常就是有异于常态,和正常情况不一样,有错误出错.在java中,阻止当前方法或作用域的情况,称之为异常. java中异常的体系是怎么样的呢? 1.Java中的所有不正常类都 ...
- [转]C#集合类型大揭秘
作者:撸码那些事 来源:https://www.cnblogs.com/songwenjie/p/9185790.html 集合是.NET FCL(Framework Class Library)的重 ...
- 第二大矩阵面积--(stack)牛客多校第二场-- Second Large Rectangle
题意: 给你一幅图,问你第二大矩形面积是多少. 思路: 直接一行行跑stack求最大矩阵面积的经典算法,不断更新第二大矩形面积,注意第二大矩形可能在第一大矩形里面. #define IOS ios_b ...