Go语言之并发编程练习

GO协程初识

package main

import (
	"fmt"
	"sync"
	"time"
)

func read() {
	defer wg.Done()
	fmt.Println("read start")
	time.Sleep(time.Second * 3)
	fmt.Println("read end")
}

func listenMusci() {
	defer wg.Done()
	fmt.Println("listenMusci start")
	time.Sleep(time.Second * 5)
	fmt.Println("listenMusci end")
}

var wg sync.WaitGroup //声明一把锁,同步的一个等待锁,本质是一个计时器,所有的进程都可以共享

func main() {
	start := time.Now().Unix()

	wg.Add(2)
	go read()        //开启GO并发
	go listenMusci() //开启GO并发

	wg.Wait() //计数器为0继续执行

	//time.Sleep(time.Second * 10) //将main主线程阻塞下

	end := time.Now().Unix()
	fmt.Println(end - start)
}

输出结果:
Go语言之并发编程练习_第1张图片

互斥锁

package main

import (
	"fmt"
	"sync"
	"time"
)

/*
	互斥锁!!!
互斥锁是一种常用的控制共享资源访问的方法,它能够保证同时只有
一个goroutine可以访问共享资源。Go语言中使用sync包的Mutex类型来实现互斥锁。

使用互斥锁能够保证同一时间有且只有一个goroutine进入临界区,
其他的goroutine则在等待锁;当互斥锁释放后,等待的goroutine才可以获取锁进入临界区,
多个goroutine同时等待一个锁时,唤醒的策略是随机的。
*/
var wg sync.WaitGroup //声明一把锁,同步的一个等待锁,本质是一个计时器,所有的进程都可以共享
var lock sync.Mutex

var x = 0

func add() {
	defer wg.Done()

	//加锁,互斥锁
	lock.Lock()
	x++
	lock.Unlock()

	println(x)
	time.Sleep(time.Second * 10) //
}
func main() {
	wg.Add(100)
	for i := 0; i < 100; i++ {
		go add()
	}
	wg.Wait() //计数器为0继续执行

	fmt.Println(x)
}

管道:channel的读写操作

package main

import (
	"fmt"
	"reflect"
)

/*
	管道:channel的读写操作!!!
	chan是go的协程之间通信的数据类型(引用类型)
	没有索引的概念,取完第一个才能取第二个
*/
func 声明一个管道() {
	//声明一个管道
	var ch = make(chan int, 3)
	//插入值
	ch <- 12
	ch <- 13
	ch <- 15
	//取值
	fmt.Println(<-ch)
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}

//声明一个结构体
type Msg struct {
	content string
	from    string
}

func main() {
	var ch = make(chan interface{}, 6)
	ch <- "hello"
	ch <- true
	ch <- 15
	ch <- Msg{content: "from kegog", from: "中国北京"}
	one := <-ch
	fmt.Println(one, reflect.TypeOf(one))

	fmt.Println(<-ch)

	fmt.Println(<-ch)

	//fmt.Println(<-ch)
	fmt.Println((<-ch).(Msg).content)
}

管道关闭后不能再写入值了

package main

import "fmt"

/*
	管道的关闭与循环!!
*/
func 管道关闭后不能再写入值了() {
	ch3 := make(chan int, 10)
	ch3 <- 1
	ch3 <- 2
	ch3 <- 3

	close(ch3)
	fmt.Println(<-ch3)
	ch3 <- 4
}
func main() {
	管道关闭后不能再写入值了()
}

遍历管道之前要先关闭管道close

package main

import (
    "fmt"
    "time"
)

func main() {

    ch := make(chan int, 10)
    ch <- 1
    ch <- 2
    ch <- 3

    // 方式1
    go func() {
        time.Sleep(time.Second * 10)
        ch <- 4

    }()

    for v := range ch {

        fmt.Println(v, len(ch))
        // 读取完所有值后,ch的sendq中没有groutine
        if len(ch) == 0 { // 如果现有数据量为0,跳出循环
            break
        }
    }

    close(ch)
    for i := range ch {
        fmt.Println(i)
    }

}

生产者消费者

package main

import (
	"fmt"
	"sync"
	"time"
)

func producer(ch chan<- int) {
	defer wg.Done()
	for i := 1; i < 11; i++ {
		time.Sleep(time.Second)
		ch <- i
		fmt.Println("生产了:", i)
	}
	close(ch)
}

func consumer(ch <-chan int) {
	defer wg.Done()
	for i := range ch {
		fmt.Println("消费了:", i)
	}
}

var wg sync.WaitGroup

func main() {
	ch := make(chan int, 100)

	wg.Add(2)
	go producer(ch)
	go consumer(ch)

	wg.Wait()
	fmt.Println("process end")
}

Go语言之并发编程练习_第2张图片

你可能感兴趣的:(Golang,golang,开发语言,后端)