GO语言自学_017_多go程

无缓冲通道代码
package main

import (
  "fmt"
)

func main() {
  /*
    当涉及到多go程时,go语言使用channel通道
    不需要加锁解锁
    例子:A向通道里写数据 -> B从通道里读数据(go自动帮我们做好了数据同步)
    sync.RWMutex{}
  */
  // 使用管道的时候,一定要用make。(使用map的时候用map)否则是空的,用不了的。(nil)
  // 创建管道:创建一个装数字的管道 => channel
  // strChannel := make(chan string) // 这是一个只装字符串的管道
  numChannel := make(chan int) // 这是一个只装数字的管道(无缓冲)
  //numChannelBuffer := make(chan int, 10) // 这是一个只装数字的管道(有缓冲,10个容器)
  go writeFncSub(numChannel)
  go readFncSub(numChannel)
  writeFnc(numChannel)
}

func readFncSub(channel chan int) {
  for i := 1; i <= 50; i++ {
    data := <-channel
    fmt.Println("子go程1===读数据data:", data)
  }
}

func writeFncSub(channel chan int) {
  for i := 1; i <= 20; i++ {
    channel <- i
    fmt.Println("子go程2===写入数据", i)
  }
}

func writeFnc(channel chan int) {
  for i := 21; i <= 50; i++ {
    // 向管道中写入数据,从右往左写入
    channel <- i
    fmt.Println("【这是主go程】正在写入数字:", i)
    //time.Sleep(30000 * time.Microsecond)
  }
}

无缓冲代码结果
ASUS@DESKTOP-NFP9SLA MINGW64 /c/gowork/src
$ go run 016_go_comm_channel.go 
子go程1===读数据data: 21
子go程1===读数据data: 1
子go程2===写入数据 1
子go程2===写入数据 2
【这是主go程】正在写入数字: 21
子go程1===读数据data: 2
子go程1===读数据data: 3
子go程1===读数据data: 22
子go程2===写入数据 3
子go程2===写入数据 4
【这是主go程】正在写入数字: 22
子go程1===读数据data: 4
子go程1===读数据data: 5
子go程1===读数据data: 23
【这是主go程】正在写入数字: 23
【这是主go程】正在写入数字: 24
子go程2===写入数据 5
子go程1===读数据data: 24
子go程1===读数据data: 25
子go程1===读数据data: 6
【这是主go程】正在写入数字: 25
【这是主go程】正在写入数字: 26
子go程2===写入数据 6
子go程1===读数据data: 26
子go程1===读数据data: 27
子go程1===读数据data: 7
【这是主go程】正在写入数字: 27
【这是主go程】正在写入数字: 28
子go程2===写入数据 7
子go程1===读数据data: 28
子go程1===读数据data: 29
子go程1===读数据data: 8
【这是主go程】正在写入数字: 29
【这是主go程】正在写入数字: 30
子go程2===写入数据 8
子go程1===读数据data: 30
子go程1===读数据data: 31
子go程1===读数据data: 9
【这是主go程】正在写入数字: 31
【这是主go程】正在写入数字: 32
子go程2===写入数据 9
子go程1===读数据data: 32
子go程1===读数据data: 33
子go程1===读数据data: 10
【这是主go程】正在写入数字: 33
【这是主go程】正在写入数字: 34
子go程2===写入数据 10
子go程1===读数据data: 34
子go程1===读数据data: 35
子go程1===读数据data: 11
【这是主go程】正在写入数字: 35
【这是主go程】正在写入数字: 36
子go程2===写入数据 11
子go程1===读数据data: 36
子go程1===读数据data: 37
子go程1===读数据data: 12
【这是主go程】正在写入数字: 37
【这是主go程】正在写入数字: 38
子go程2===写入数据 12
子go程1===读数据data: 38
子go程1===读数据data: 39
子go程1===读数据data: 13
【这是主go程】正在写入数字: 39
【这是主go程】正在写入数字: 40
子go程2===写入数据 13
子go程1===读数据data: 40
子go程1===读数据data: 41
子go程1===读数据data: 14
【这是主go程】正在写入数字: 41
【这是主go程】正在写入数字: 42
子go程2===写入数据 14
子go程1===读数据data: 42
子go程1===读数据data: 43
子go程1===读数据data: 15
【这是主go程】正在写入数字: 43
【这是主go程】正在写入数字: 44
子go程2===写入数据 15
子go程1===读数据data: 17
【这是主go程】正在写入数字: 47
【这是主go程】正在写入数字: 48
子go程2===写入数据 17
子go程1===读数据data: 48
子go程1===读数据data: 49
子go程1===读数据data: 18
【这是主go程】正在写入数字: 49
【这是主go程】正在写入数字: 50

有缓冲通道代码
package main

import (
	"fmt"
	"time"
)

func main() {
	//numChan := make(chan int, 10)
	/*
	 当缓冲写满,写阻塞;当读完之后,恢复写入。
	 当缓冲区读取完毕,读阻塞。
	 如果管道没有使用make空间,管道默认是nil,读取写入都会阻塞。
	 对于一个管道,读与写的次数,必须对等。(不对等会死锁)
	*/
	var names chan string //默认是nil
	names = make(chan string, 10)
	go func() {
		fmt.Println("names: ", <-names)
	}()
	names <- "hello" // 如果names是nil,写操作会阻塞在这里。
	fmt.Println("names:", names)
	time.Sleep(1 * time.Second)

	/*
		错误案例:当读写次数不一致时,出现死锁。
	*/
	numsChan := make(chan int, 10)
	// 写入
	go func() {
		for i := 1; i <= 10; i++ {
			numsChan <- i
			fmt.Println("写入:", i)
		}
	}()
	// 1、读取,主程序被管道阻塞时,程序将锁死。
	// 2、读取,子go程go func()时,程序虽然不会卡死,单这个子go程会一直阻塞,造成内存泄漏!
	func() {
		for i := 1; i <= 11; i++ {
			fmt.Println("主程序准备读取数据...")
			data := <-numsChan
			fmt.Println("读取:", data)
		}
	}()
	for {
		//fmt.Println("主程序:我在死循环")
	}

}

有缓冲通道代码结果
ASUS@DESKTOP-NFP9SLA MINGW64 /c/gowork/src
$go run 017_go_comm_channel_buffer.go 
names: 0xc00007c060
names:  hello
主程序准备读取数据...
读取: 1
主程序准备读取数据...
写入: 1
写入: 2
写入: 3
写入: 4
写入: 5
写入: 6
写入: 7
写入: 8
写入: 9
写入: 10
读取: 2
主程序准备读取数据...
读取: 3
主程序准备读取数据...
读取: 4
主程序准备读取数据...
读取: 5
主程序准备读取数据...
读取: 6
主程序准备读取数据...
读取: 7
主程序准备读取数据...
读取: 8
主程序准备读取数据...
读取: 9
主程序准备读取数据...
读取: 10
主程序准备读取数据...
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main.func3(0x3b9aca00?)
        C:/gowork/src/017_go_comm_channel_buffer.go:41 +0x87
main.main()
        C:/gowork/src/017_go_comm_channel_buffer.go:44 +0x145
exit status 2

posted @ 2022-09-08 20:59  顺心无忧  阅读(33)  评论(0编辑  收藏  举报