go channel实现线程同步

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangpengzp/article/details/88417234

go channel是通过通信来实现 共享内存,以及线程同步的,而不是通过共享内存来实现线程通信的.

channel创建

channel数据读写

线程同步

channel是通过读取通道里的数据,然后来实现同步的。如下例子:

package main

import (
	"fmt"
	)
var ch = make(chan int)
func lammySay(){
	str :="hello, i am lammy! who are you ?"
	for _, i := range str{
		fmt.Printf("%c",i)
	}
	fmt.Println()
// 向channel存取数据
	ch <- 666

}
func lalalaSay(){
	//取到数据之前 堵塞
	<-ch
	str :="i am lalala , how do you do !"
	for _, i := range str{
		fmt.Printf("%c",i)
	}
}
func main() {

	go lammySay()
	go lalalaSay()

	for{
		fmt.Print()
	}

}

执行:

无缓冲区: 存入读取一次,存入后未取,再存入就会堵塞,同样未存,就取也会堵塞。

有缓冲区: 只有当缓冲区满了,才会堵塞存;只有缓冲区空时,才会堵塞取。

len(channel)  返回缓冲区现有数据长度

cap(channel) 返回缓冲区的大小

close(channel关闭 channel,关闭后,读取不到数据。如下,如果其他协程关掉 channel 则会跳出循环

遍历channel:

// 如果读取到数据,则 打印,没有数据 则堵塞, ok为flase则管道关闭
		if num, ok := <- ch; ok==true{
			fmt.Println(num)
		}else {
			// 如果没有读取到 管道关闭
			fmt.Println("管道关闭了")
			break
		}


// range 遍历
    
    for num := range ch {
        fmt.Println(num)
}

下面的例子,是有缓冲区的例子:

lammysay是打电话的一方,写入要拨打的对象

answerSay 是接电话处理机制,根据lammy拨打的对象参数 who来决定谁来回复

缓冲区size为2,因此,当打第三个人的时候,则需要等待前2个拨打的取出数据才能,继续拨打

package main

import (	
	"fmt"
	)
var ch = make(chan string , 2)
func lammyCall(who string ){
	str :="hello, i am lammy! how do you do"
	fmt.Println(str)
	ch <- who
	fmt.Println()

}
func answerSay(){
	for {
		//取到数据之前 堵塞
		a := <-ch
		if a == "lalala" {
			str := "i am lalala , how do you do !"
			fmt.Printf("%s", str)
			fmt.Println()
		}
		if a == "hahaha" {
			str := "i am hahaha , how do you do !"
			fmt.Printf("%s", str)
			fmt.Println()
		}
		if a == "hehehe" {
			str := "i am hehehe , how do you do !"
			fmt.Printf("%s", str)
			fmt.Println()
		}
	}
}
func main() {

	go lammyCall("lalala")
	go lammyCall("hahaha")
	go lammyCall("hehehe")
	go answerSay()


	for{
		fmt.Print()
	}

}

执行的结果不唯一,跟 写入channel的who的顺序有关系,即cpu时间轮片有关,这里贴出一次执行的结果:

单通道 channel

猜你喜欢

转载自blog.csdn.net/zhangpengzp/article/details/88417234