goroutine channel_互斥锁

goroutine channel_goroutine_02

goroutine channel_数据_03

goroutine channel_i++_04

goroutine channel_数据_05

goroutine channel_goroutine_06

goroutine channel_互斥锁_07

goroutine channel_i++_08

goroutine channel_互斥锁_09


 goroutine channel_goroutine_10

goroutine channel_数据_11

goroutine channel_i++_12

goroutine channel_i++_13

goroutine channel_goroutine_14

goroutine channel_互斥锁_15


 goroutine channel_数据_16

goroutine channel_数据_17

goroutine channel_i++_18

package main
import (
"fmt"
_ "time"
"sync"
)

// 需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到map中。
// 最后显示出来。要求使用goroutine完成

// 思路
// 1. 编写一个函数,来计算各个数的阶乘,并放入到 map中.
// 2. 我们启动的协程多个,统计的将结果放入到 map中
// 3. map 应该做出一个全局的.

var (
myMap = make(map[int]int, 10)
//声明一个全局的互斥锁
//lock 是一个全局的互斥锁,
//sync 是包: synchornized 同步
//Mutex : 是互斥
lock sync.Mutex
)


//使用协程+管道 ===>???

// test 函数就是计算 n!, 让将这个结果放入到 myMap
func test(n int) {

res := 1
for i := 1; i <= n; i++ {
res *= i
}

//这里我们将 res 放入到myMap
//加锁
lock.Lock()
myMap[n] = res //concurrent map writes?
//解锁
lock.Unlock()
}

func main() {

// 我们这里开启多个协程完成这个任务[200个]
for i := 1; i <= 20; i++ {
go test(i)
}


//休眠10秒钟【第二个问题 】
//time.Sleep(time.Second * 5)

//这里我们输出结果,变量这个结果
lock.Lock()
for i, v := range myMap {
fmt.Printf("map[%d]=%d\n", i, v)
}
lock.Unlock()

}


goroutine channel_数据_19

goroutine channel_互斥锁_20

goroutine channel_goroutine_21

goroutine channel_goroutine_22

goroutine channel_互斥锁_23



package main
import (
"fmt"
)

func main() {

//演示一下管道的使用
//1. 创建一个可以存放3个int类型的管道
var intChan chan int
intChan = make(chan int, 3)

//2. 看看intChan是什么
fmt.Printf("intChan 的值=%v intChan本身的地址=%p\n", intChan, &intChan)


//3. 向管道写入数据
intChan<- 10
num := 211
intChan<- num
intChan<- 50
// //如果从channel取出数据后,可以继续放入
<-intChan
intChan<- 98//注意点, 当我们给管写入数据时,不能超过其容量


//4. 看看管道的长度和cap(容量)
fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 3, 3

//5. 从管道中读取数据

var num2 int
num2 = <-intChan
fmt.Println("num2=", num2)
fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 2, 3

//6. 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock

num3 := <-intChan
num4 := <-intChan

//num5 := <-intChan

fmt.Println("num3=", num3, "num4=", num4/*, "num5=", num5*/)

}
intChan 的值=0xc000086080 intChan本身的地址=0xc000080018
channel len= 3 cap=3
num2= 211
channel len= 2 cap=3
num3= 50 num4= 98


goroutine channel_i++_24

goroutine channel_i++_25


goroutine channel_互斥锁_26

goroutine channel_数据_27

package main

import "fmt"

func main() {
var mapchan chan map[string]string
mapchan = make(chan map[string]string,10)

m1 := make(map[string]string,10)
m1["name"] = "阿凡达"
m1["age"] = "25"
m2 := make(map[string]string,10)
m2["name"] = "欧阳"
m2["age"] = "28"
mapchan <- m1
mapchan <- m2
fmt.Println(mapchan)
}

goroutine channel_goroutine_28

goroutine channel_数据_29

goroutine channel_数据_30

goroutine channel_goroutine_31


goroutine channel_互斥锁_32

package main

import "fmt"

func main() {
intchan := make(chan int ,3)
intchan <- 100
intchan <- 200
close(intchan)
fmt.Println("11111111111")
n1 := <-intchan
fmt.Println(n1) //100
fmt.Println(<-intchan) //200
fmt.Println(<-intchan) //0
fmt.Println(<-intchan) //0
intchan <- 300 //panic: send on closed channel
}

goroutine channel_数据_33

goroutine channel_数据_34


goroutine channel_i++_35

goroutine channel_数据_36goroutine channel_互斥锁_37

package main
import (
"fmt"
"time"
)


//write Data
func writeData(intChan chan int) {
for i := 1; i <= 50; i++ {
//放入数据
intChan<- i //
fmt.Println("writeData ", i)
//time.Sleep(time.Second)
}
close(intChan) //关闭
}

//read data
func readData(intChan chan int, exitChan chan bool) {

for {
v, ok := <-intChan
if !ok {
break
}
time.Sleep(time.Second)
fmt.Printf("readData 读到数据=%v\n", v)
}
//readData 读取完数据后,即任务完成
exitChan<- true
close(exitChan)

}

func main() {

//创建两个管道
intChan := make(chan int, 10)
exitChan := make(chan bool, 1)

go writeData(intChan)
go readData(intChan, exitChan)

//time.Sleep(time.Second * 10)
for {
_, ok := <-exitChan
if !ok {
break
}
}

}

View Code

 goroutine channel_互斥锁_38

goroutine channel_数据_39




goroutine channel_i++_40



goroutine channel_数据_36goroutine channel_互斥锁_37

package main
import (
"fmt"
"time"
)



//向 intChan放入 1-8000个数
func putNum(intChan chan int) {

for i := 1; i <= 80000; i++ {
intChan<- i
}

//关闭intChan
close(intChan)
}

// 从 intChan取出数据,并判断是否为素数,如果是,就
// //放入到primeChan
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {

//使用for 循环
// var num int
var flag bool //
for {
//time.Sleep(time.Millisecond * 10)
num, ok := <-intChan //intChan 取不到..

if !ok {
break
}
flag = true //假设是素数
//判断num是不是素数
for i := 2; i < num; i++ {
if num % i == 0 {//说明该num不是素数
flag = false
break
}
}

if flag {
//将这个数就放入到primeChan
primeChan<- num
}
}

fmt.Println("有一个primeNum 协程因为取不到数据,退出")
//这里我们还不能关闭 primeChan
//向 exitChan 写入true
exitChan<- true

}

func main() {

intChan := make(chan int , 1000)
primeChan := make(chan int, 20000)//放入结果
//标识退出的管道
exitChan := make(chan bool, 8) // 4个



start := time.Now().Unix()

//开启一个协程,向 intChan放入 1-8000个数
go putNum(intChan)
//开启4个协程,从 intChan取出数据,并判断是否为素数,如果是,就
//放入到primeChan
for i := 0; i < 8; i++ {
go primeNum(intChan, primeChan, exitChan)
}

//这里我们主线程,进行处理
//直接
go func(){
for i := 0; i < 8; i++ {
<-exitChan
}

end := time.Now().Unix()
fmt.Println("使用协程耗时=", end - start)

//当我们从exitChan 取出了4个结果,就可以放心的关闭 prprimeChan
close(primeChan)
}()


//遍历我们的 primeChan ,把结果取出
for {
_, ok := <-primeChan
if !ok{
break
}
//将结果输出
//fmt.Printf("素数=%d\n", res)
}

fmt.Println("main线程退出")



}

View Code


 goroutine channel_数据_43

   goroutine channel_互斥锁_44


goroutine channel_互斥锁_45


goroutine channel_数据_36goroutine channel_互斥锁_37

package main

import "fmt"
func send(ch chan<- int,exitchan chan struct{}){
for i :=0 ; i<10 ;i++{
ch<- i
}
close(ch)
var a struct{}
exitchan<- a
}
func recv(ch <-chan int,exitchan chan struct{}){
for{
v,ok:= <-ch
if !ok{
break
}
fmt.Println(v)
}
var a struct{}
exitchan<- a
}



func main() {
var ch chan int
ch = make(chan int,10)
exitchan := make(chan struct{},2)

go send(ch,exitchan)
go recv(ch,exitchan)

//var total = 0
//for _ = range exitchan{
// total++
// if total ==2{
// break
// }
//}
var total = 0
for{
_,ok:= <-exitchan
if !ok{
break
}
total++
if total ==2{
break
}
}
fmt.Println("结束")

}

View Code

 goroutine channel_i++_48

goroutine channel_数据_49


goroutine channel_数据_36goroutine channel_互斥锁_37

package main

import "fmt"


func main() {

intchan := make(chan int,10)
for i := 0;i<10;i++{
intchan <- i
}

stringchan := make(chan string ,5)

for i:=0;i<5;i++{
stringchan<- "hello"+fmt.Sprintf("%d",i)
}

for{
select{
case v:= <-intchan:
fmt.Printf("从intchan读取的数据%d\n",v)
case v := <-stringchan:
fmt.Printf("从stringchan读取的数据%d\n",v)
default:
fmt.Printf("都取不到了,不玩了")
return
}
}
}

View Code


goroutine channel_goroutine_52

package main

import (
"time"
"fmt"
)

func sayHello(){
for i:=0;i<10;i++{
//time.Sleep(time.Second)
fmt.Println("hello world")
}
}

func test(){
defer func(){
if err := recover();err!=nil{
fmt.Println("test() 发生错误",err)
}
}()
var myMap map[int]string
//myMap = make(map[int]string,6)
myMap[0] = "golang"
}


func main() {
go sayHello()
go test()

time.Sleep(time.Second*10)

}


 sync:

goroutine channel_goroutine_53

goroutine channel_i++_54


 goroutine channel_goroutine_55


 sync案例

goroutine channel_i++_56

上图每次执行结果都不相同

通过加互斥锁

goroutine channel_i++_57