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的更多相关文章

  1. 10.Go-goroutine,waitgroup,互斥锁和channel

    10.1.goroutine goroutine的使用 //Learn_Go/main.go package main import ( "fmt" "time" ...

  2. liteos互斥锁(七)

    1. 概述 1.1 基本概念 互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理. 任意时刻互斥锁的状态只有两种,开锁或闭锁.当有任务持有时,互斥锁处于闭锁状态,这个任务 ...

  3. 多图详解Go的互斥锁Mutex

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码时14.4 Mutex介绍 Mutex 结构体包含两个字段: 字段s ...

  4. 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 百篇博客分析OpenHarmony源码 | v27.02

    百篇博客系列篇.本篇为: v27.xx 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁当立贞 ...

  5. goroutiine同步/channel、互斥锁、读写锁、死锁/条件变量

    1. Goroutine同步[数据同步] 为什么需要goroutine同步 gorotine同步概念.以及同步的几种方式 1.1 为什么需要goroutine同步 package main impor ...

  6. Go基础系列:互斥锁Mutex和读写锁RWMutex用法详述

    sync.Mutex Go中使用sync.Mutex类型实现mutex(排他锁.互斥锁).在源代码的sync/mutex.go文件中,有如下定义: // A Mutex is a mutual exc ...

  7. Go语言基础之13--线程安全及互斥锁和读写锁

    一.线程安全介绍 1.1 现实例子 A. 多个goroutine同时操作一个资源,这个资源又叫临界区 B. 现实生活中的十字路口,通过红路灯实现线程安全 C. 火车上的厕所(进去之后先加锁,在上厕所, ...

  8. Go同步等待组/互斥锁/读写锁

    1. 临界资源 package main import ( "fmt" "time" ) func main() { /* 临界资源: */ a := 1 go ...

  9. Go语言中的互斥锁和读写锁(Mutex和RWMutex)

    目录 一.Mutex(互斥锁) 不加锁示例 加锁示例 二.RWMutex(读写锁) 并发读示例 并发读写示例 三.死锁场景 1.Lock/Unlock不是成对出现 2.锁被拷贝使用 3.循环等待 虽然 ...

随机推荐

  1. python安装二进制k8s 1.11.0 一个master、一个node 查看node节点是主机名---apiserver无法启动,后来改了脚本应该可以

    一.脚本说明: 本实验中master.node.etcd都是单体. 安装顺序为:先安装test1节点主要组件,然后开始安装test2节点,最后回头把test1节点加入集群中,这样做目的是理解以后扩容都 ...

  2. 【VS开发】CTimeSpan类

    CTimeSpan类.        日期和时间类简介        CTime类的对象表示的时间是基于格林威治标准时间(GMT)的.CTimeSpan类的对象表示的是时间间隔.        CTi ...

  3. Python全栈开发之3、深浅拷贝、变量和函数、递归、函数式编程、内置函数

    一.深浅拷贝 1.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. import copy # 定义变量 数字.字符串 # n1 = 123 n1 ...

  4. PTA(Basic Level)1030.完美数列

    给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤*m**p*,则称这个数列是完美数列. 现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列. ...

  5. codeforces 620C

    题目链接:https://codeforces.com/problemset/problem/620/C 题目分析 题意:给你一串珍珠,每个珍珠都有一个对应值,需要分割这n个珍珠(必须连续),使得每一 ...

  6. python之函数、面向对象

    学习python到了函数这一块进度有所放缓,主要还是想理解透彻,毕竟直觉告诉我函数是python是其中的关键,不管是模块.还是包.或者是库,都是建立在若干个函数定义上面. 章节后面就是关于面向对象编程 ...

  7. CVE-2018-20169漏洞学习

    简介 在4.19.9之前的Linux内核中发现了一个问题.USB子系统在读取与驱动程序/ USB /core/usb.c中的_usb_get_extra_descriptor相关的额外描述符时错误地检 ...

  8. jQuery俄罗斯方块游戏动画

    在线演示       本地下载

  9. Mysql主从分离介绍及实现

    参考: http://www.cnblogs.com/panxuejun/p/5887118.html https://www.cnblogs.com/alvin_xp/p/4162249.html ...

  10. Antdesign Form 实现页面控件的赋值加载

    使用Antdesign Form时,当页面加载时,需要从后台获取数据,对Form中控件的默认赋值.看似比较简单的需求,而且Antdesign 官方文档中也有相应介绍,然后对于Form 的CheckBo ...