go之并发编程

一.go关键字

1.概念
(1).通过关键字 go 来创建 goroutine
(2).所有的go函数都是并发执行的,谁先谁后并不能确定
(3).go函数是可以有结果声明的,但它们返回的结果值会在其执行完成后被丢弃。如果想把go函数的计算结果传递给其他go函数,将通过Channel来实现
2.例子

package main

import (
	"fmt"
)
func Goroutine_simple_many_who() {
	str := []string{"1111\n", "2222\n", "3333\n", "4444\n"}
	for _, pr := range str {
		go func() {
			fmt.Print(pr)
		}()
	}
}

func Goroutine_simple_many_order() {
	str := []string{"1111\n", "2222\n", "3333\n", "4444\n"}
	for _, pr := range str {
		go func(name string) {
			fmt.Print(name)
		}(pr)
	}
}
func main() {
	//并发的执行的5个go函数,打印的值都是4444。
	//这是因为它们都是在for语句执行完之后才执行的。而pr在这时已经被赋值给了Mark
	Goroutine_simple_many_who()
	//发现都能打印出来,但顺序不定
	//func使用参数name,每次pr被赋值的时候,对应的值都会被传递给name这个参数
	//因此当go函数执行的时候,就是对应的数据
	Goroutine_simple_many_order()
}

二.chan关键字(channel)

1、channel类型表示法:
(1).使用关键字chan
2、概念
(1).在同一时刻,仅有一个goroutine能向一个通道发送元素值,同时也仅有一个gorountine能从它那里接收元素值
(2).先进先出
(3).具有原子性,不可分割
(4).通道中每一个元素值都只能被某一个goroutine接收,已被接收会被立即删除
(5).从channel读数据,如果channel缓冲区为空或者没有缓冲区,当前goroutine会被阻塞。
向channel写数据,如果channel缓冲区已满或者没有缓冲区,当前goroutine会被阻塞
3、初始化
(1).声明

type chan_int chan intvar chan_int chan int

(2)初始化

make(chan int,10)

4.slect配合使用
(1).select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收

(2).select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行
5.出让时间片段
runtime.Gosched函数
runtime.Gosched函数的作用是暂停调用他的Goroutine的运行,调用他的Goroutine会被重新置于Gorunnable状态,并被放入调度器可运行G队列中
6.注意事项
在这里插入图片描述

7.例子

package main

import (
	"fmt"
	"runtime"
)
//无缓冲
var chan_int_no_buffer chan int

//缓冲
var chan_int_buffer_str chan string

//缓冲结构体
var chan_int_buffer_struct chan person
//退出通道
var Chan_close chan bool

func Goroutine_channel_no_buffer() {
	//初始化
	chan_int_no_buffer = make(chan int)
	go func() {
		chan_int_no_buffer <- 2
		fmt.Printf("发送数据chan_int_no_buffer\n")
	}()
	go func() {
		value := <-chan_int_no_buffer
		fmt.Printf("接收数据 chan_int_no_buffer: %d\n", value)
	}()
	time.Sleep(2 * time.Second)
}

func Goroutine_channel_buffer() {
	chan_int_buffer_str = make(chan string, 2)
	chan_number := []string{"1111", "2222", "3333", "4444", "5555", "6666"}
	//1个接收者
	go func() {
		for {
			if value, ok := <-chan_int_buffer_str; ok {
				fmt.Println("Goroutine_channel_buffer接收数据完成:" + value + "\n")
			} else {
				fmt.Println("Goroutine_channel_buffer关闭:" + "\n")
				break
			}
		}
	}()
	for _, number := range chan_number {
		go func(num string) {
			fmt.Println("Goroutine_channel_buffer开始发送数据:" + num + "\n")
			chan_int_buffer_str <- num
		}(number)
	}
}
func Goroutine_channel_buffer_struct() {
	chan_int_buffer_struct = make(chan person, 2)
	chan_number := []person{
		{
			"LI",
			"1111",
			"23",
		},
		{
			"Wang",
			"2222",
			"24",
		},
	}
	//1个接收者
	go func() {
		for {
			if value, ok := <-chan_int_buffer_struct; ok {
				fmt.Println("chan_int_buffer_struct接收数据完成:" + value.Name + "--" + value.ID + "--" + value.Age + "\n")
			} else {
				fmt.Println("chan_int_buffer_struct关闭:" + "\n")
				break
			}
		}
	}()
	for _, number := range chan_number {
		go func(num person) {
			fmt.Println("chan_int_buffer_struct开始发送数据:" + num.Name + "--" + num.ID + "--" + num.Age + "\n")
			chan_int_buffer_struct <- num
		}(number)
	}
}

//select 多路复用
func Goroutine_channel_buffer_select() {
	chan_int_buffer_struct = make(chan person, 2)
	chan_int_buffer_str = make(chan string, 2)
	chan_int_no_buffer = make(chan int)
	Chan_close = make(chan bool)
	chan_number := []person{
		{
			"LI",
			"1111",
			"23",
		},
		{
			"Wang",
			"2222",
			"24",
		},
	}
	chan_number_str := []string{"1111", "2222", "3333", "4444", "5555", "6666"}
	for _, number := range chan_number {
		go func(num person) {
			fmt.Println("chan_int_buffer_struct开始发送数据:" + num.Name + "--" + num.ID + "--" + num.Age + "\n")
			chan_int_buffer_struct <- num
		}(number)
	}

	for _, number := range chan_number_str {
		go func(num string) {
			runtime.Gosched() //出让时间片段
			fmt.Println("Goroutine_channel_buffer开始发送数据:" + num + "\n")
			chan_int_buffer_str <- num
		}(number)
	}

	go func() {
		chan_int_no_buffer <- 2
		fmt.Printf("发送数据chan_int_no_buffer\n")
	}()

	go func() {
		defer close(chan_int_buffer_str)
		defer close(chan_int_no_buffer)
		defer close(chan_int_buffer_struct)
		for {
			select {
			case str_tmp := <-chan_int_buffer_str:
				fmt.Println("Goroutine_channel_buffer接收数据完成:" + str_tmp + "\n")
			case struct_tmp := <-chan_int_buffer_struct:
				fmt.Println("chan_int_buffer_struct接收数据完成:" + struct_tmp.Name + "--" + struct_tmp.ID + "--" + struct_tmp.Age + "\n")
			case int_tmp := <-chan_int_no_buffer:
				fmt.Printf("接收数据 chan_int_no_buffer: %d\n", int_tmp)
			case <-Chan_close:
				fmt.Printf("结束select\n")
				return
			}
		}
	}()
}
func main() {
	//无缓冲
	//Goroutine_channel_no_buffer()
	//有缓冲
	//Goroutine_channel_buffer()
	//缓冲结构体
	//Goroutine_channel_buffer_struct()
	//select多路复用以及出让时间片段
	Goroutine_channel_buffer_select()
	time.Sleep(time.Duration(2) * time.Second)
	close(Chan_close)
	time.Sleep(time.Duration(1) * time.Second)
}

8.例子优化

1.上面例子未实现channel关闭以及CPU利用以及同步动作。
优化方案2sync.WaitGroup同步操作,3channel关闭

package main

import (
	"fmt"
	"runtime"
	"sync"
	"time"
)
//无缓冲
var chan_int_no_buffer chan int

//缓冲
var chan_int_buffer_str chan string

//缓冲结构体
var chan_int_buffer_struct chan person
//退出通道
var Chan_close chan bool
//select 多路复用
//优化方案1.FAN模式优化时间使用.2sync.WaitGroup同步操作,3channel关闭

func Goroutine_channel_buffer_select_optimize(wg *sync.WaitGroup) {
	chan_int_buffer_struct = make(chan person, 2)
	chan_int_buffer_str = make(chan string, 2)
	chan_int_no_buffer = make(chan int)
	Chan_close = make(chan bool)
	chan_number := []person{
		{
			"LI",
			"1111",
			"23",
		},
		{
			"Wang",
			"2222",
			"24",
		},
	}
	chan_number_str := []string{"1111", "2222", "3333", "4444", "5555", "6666"}
	for _, number := range chan_number {
		wg.Add(1)
		go func(num person) {
			fmt.Println("chan_int_buffer_struct开始发送数据:" + num.Name + "--" + num.ID + "--" + num.Age + "\n")
			chan_int_buffer_struct <- num
		}(number)
	}

	for _, number := range chan_number_str {
		wg.Add(1)
		go func(num string) {
			runtime.Gosched() //出让时间片
			fmt.Println("Goroutine_channel_buffer开始发送数据:" + num + "\n")
			chan_int_buffer_str <- num
		}(number)
	}

	go func() {
		chan_int_no_buffer <- 2
		wg.Add(1)
		fmt.Printf("发送数据chan_int_no_buffer\n")
	}()

	go func() {
		for {
			select {
			case str_tmp := <-chan_int_buffer_str:
				fmt.Println("Goroutine_channel_buffer接收数据完成:" + str_tmp + "\n")
				wg.Done()
			case struct_tmp := <-chan_int_buffer_struct:
				fmt.Println("chan_int_buffer_struct接收数据完成:" + struct_tmp.Name + "--" + struct_tmp.ID + "--" + struct_tmp.Age + "\n")
				wg.Done()
			case int_tmp := <-chan_int_no_buffer:
				fmt.Printf("接收数据 chan_int_no_buffer: %d\n", int_tmp)
				wg.Done()
			case <-Chan_close:
				fmt.Printf("结束select\n")
				return
			}
		}
	}()
}
func Finish() {
	defer func() {
		close(chan_int_buffer_str)
		fmt.Println("关闭信道:" + "\n")
	}()
	defer close(chan_int_no_buffer)
	defer close(chan_int_buffer_struct)
}
func main() {
	//无缓冲
	//Goroutine_channel_no_buffer()
	//有缓冲
	//Goroutine_channel_buffer()
	//缓冲结构体
	//Goroutine_channel_buffer_struct()
	//select多路复用以及出让时间片段
	var wg_struct sync.WaitGroup
	Goroutine_channel_buffer_select_optimize(&wg_struct)
	wg_struct.Wait()
	close(mytools.Chan_close)
	Finish()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值