go中channel的部分理解

  学习go语言差不多也有一周了,笔记也记了不少了。但是对于go这种新语言,并没有从功能方面去了解过。毕竟,要是从思想上来认识它,对我来说还是有难度的。所以我对go的理解现在还是在一些比较基础的层次,都是对比其与我熟悉的其他语言的异同。铺垫了这么多,就是想说,我的理解可能是片面的,甚至是错的,希望各位大牛指点啊!

     在某处剽窃了关于go语言的说明:是一个在语言层面实现了并发机制的类C通用型编程语言。而在并发实现中,主要是用channel来实现通信的。其中channel包括两种,缓冲的channel和非缓冲的channel。(由于个人组织语言的能力有限,也怕说错,后面一句也是剽窃别人的)缓冲的channel:保证往缓冲中存数据先于对应的取数据,简单说就是在取的时候里面肯定有数据,否则就因取不到而阻塞。而非缓冲的channel:保证取数据先于存数据,就是保证存的时候肯定有其他的goroutine在取,否则就因放不进去而阻塞。单单看这个字面意思,其实还是不知所以然,那就。。。。。。上例子。其实好多时候,真的是懒得去解释什么,也不太喜欢跟别人讨论到底该是什么结果,直接试试比说多少都更有意义啊。可是,偏偏有那么一小撮人,非要整个面红耳赤,还不屑于我说的试试,说“我要是想试还用问你啊?”。碰到这样的人,算我倒霉。从开始学编程,老师就告诉我们,拿到问题先分析,到底结果怎样,动手实践下,再分析原因。好吧,我好像又扯远了。言归正传,谈channel。

  

 1 package main
 2 import(
 3              "fmt"
 4           )
 5 
 6 var a string
 7 var c = make(chan int,3)//此处定义为缓冲的channel
 8 func ff(){
 9           a ="hello world"
10           ca := <-c
11           fmt.Println(ca)
12         }
13 
14 func  main(){
15            go ff()      //开启一个goroutine
16           c<-3
17           fmt.Println(a)
18          
19            }

可以先试想下运行结果。其结果就是,没有任何输出,程序直接就结束了。我的理解:因为这是个缓冲的channel(var c = make(chan int,3)),所以存的优先级会高,如果存入缓冲的不足三个,那就等下去(名词叫阻塞),等到程序都结束了。这里要好好理解阻塞的含义。刚开始我以为阻塞只是阻止了channel变量的读取,后来试了几次才知道,所谓的阻塞,说白了就是什么都不干了,就等着某个条件满足之后才会有事件的执行。

  然后改变参数或者是做一些比较小的改动,看程序的运行结果是否会发生变化。在16行后面再增加两个存值操作,c<-11 ;c<-12数值是多少无所谓,因为就只有一次取,取到的肯定是存进去的第一个值。可以猜一下这次的运行结果。这次,跟原来一样,还是没有输出,因为三次存操作之后,阻塞就解开了,开始执行取操作,但是取完之后缓冲中又不足三个了,没办法,还得阻塞,一直等到了程序结束,hello world被漫长的等待覆盖了。再增加一个存操作,就得到了结果,3  helloworld。过程大致为,当三个存满了之后,阻塞被解除了,去执行一个goroutine,即进行了一次取操作,输出3,取完之后又被阻塞,然后又存了一个,阻塞解除,执行后面的操作,输出了hello world.

  但是在上述能输出结果的基础上,在增加一个村操作,又会怎样呢?别急,试下就知道了。结果就是报错了,

死锁了,能不死锁吗,缓冲满了,还要继续往里面填,但是又没有其他的goroutine去取,只能死锁。这样的测试还可以去做很多,我也确实做了不少,然后总结出规律来。只有在缓冲满了,没有goroutine去取,却还存或者是缓冲空了,没有存的操作,却还在取都会报上面的死锁信息。如果是等待,那就只是等待了,主函数会直接结束,不报什么信息。

  关于无缓冲的,我还没有研究太清楚,待续

  大致过程就是如此,对于channel,要想清楚了,要不然去理解以后更难得程序就要麻烦了。

原文地址:https://www.cnblogs.com/lxy15329/p/learninggo.html