在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
学习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,要想清楚了,要不然去理解以后更难得程序就要麻烦了。 |
请发表评论