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. Computed Styles

    The style object offers no information about the styles that have cascaded from style sheets and aff ...

  2. 运行python manage.py 出现mportError: No module named django.core.management when using manage.py

    1 . linux下用virtualenv 创建虚拟空间环境没有安装djang,即使主机装了,否则运行python manage.py 出现mportError: No module named dj ...

  3. 【HANA系列】SAP HANA SQL计算两个日期的差值

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL计算两个 ...

  4. SQLite扫描

    SQLite的扫盲 SQLite的是一种嵌入式数据库,它的数据库就是一个文件.由于SQLite的本身是Ç写的,而且体积很小,所以经常被集成到各种应用程序中,主要在手机的应用中使用. 之前没有遇到过关于 ...

  5. PowerShell学习记录

    一.简介——连接 Powershell 是运行在windows机器上实现系统和应用程序管理自动化的命令行脚本环境.你可以把它看成是命令行提示符cmd.exe的扩充,不对,应当是颠覆. powershe ...

  6. mysql常用排查命令

    1.查看服务器使用状态 mysqladmin -uroot -p -S /tmp/mysql.sock -r -i 1 ext |\ awk -F"|" \ "BEGIN ...

  7. Linux动态链接之GOT与PLT

    转载于:http://www.cnblogs.com/xingyun/archive/2011/12/10/2283149.html   我们知道函数名就是一个内存地址,这个地址指向函数的入口.调用函 ...

  8. [转帖]$PWD 和 $(pwd)

    $PWD 和 $(pwd) https://blog.csdn.net/shaojwa/article/details/51894980 细节决定成败.   注意两个效果一样,但是注意大小写,PWD是 ...

  9. mysql下的sqlmode详解

    转自:https://www.cnblogs.com/Zender/p/8270833.html 阅读目录 一,sql_mode值的含义 二,ANSI模式 三,STRICT_TRANS_TABLES模 ...

  10. Linux软链接硬链接的区别

    ln是linux中又一个非常重要命令,它的功能是为某一个文件在另外一个位置建立一个同步的链接.当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在 ...