前言

以前听说什么golang一把梭什么的很厉害,到现在位置也接触golang半个多月时间了,最主要的时间都是在看document,学习语法。golang什么的变量名大小写区分公有私有神马的太坑爹了。。。最近接触到了golang最为称赞的第一个地方:goroutine。本篇博客先介绍操作系统中的一些基本语法,然后介绍一下goroutine的美妙之处。

【线程, 进程】; 【多进程,多线程】; 【并发,并行】

线程与进程概念线程:是程序执行流的最小单元,是系统独立调度和分配CPU(独立运行)的基本单位。

进程:是资源分配的基本单位。一个进程包括多个线程

区别线程与资源分配无关,它属于某一个进程,并与进程内的其他线程一起共享进程的资源。

每个进程都有自己一套独立的资源(数据),供其内的所有线程共享。

不论是大小,开销线程要更“轻量级”

一个进程内的线程通信比进程之间的通信更快速,有效。(因为共享变量)

多进程与多线程

多线程:同一时刻执行多个线程。用浏览器一边下载,一边听歌,一边看视频,一边看网页。。。

多进程:同时执行多个程序。如,同事运行YY,QQ,以及各种浏览器。

并发与并行

并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。

并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。

举个例子:

并发就是一个窗口多条队伍,多条队伍轮流使用资源。

并行就是多个窗口,每个窗口一个队伍,队伍之间并行排队。

099d7c758b504a2718df2c360ae20dc4.png

gotuntine

golang语言中,用go关键词就可以启动并发程序。

我们先看一下下面这个简单的例子,在main函数中依次调用了两次loop函数。

func loop() {

for i := 0; i < 10; i++ {

fmt.Printf("%d", i)

}

}

func main() {

loop()

loop()

}

毫无疑问上述代码的运行结果如下:

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

这个时候我们将main函数代码换成如下

func main() {

go loop()

loop()

}

此时loop函数只运行了一次;这是什么原因呢,原来是因为我们的main函数中的第二个loop()执行比较快

在go loop()还没有执行的时候,main函数已经运行结束并且退出了。

0 1 2 3 4 5 6 7 8 9

我们可以使用time.Sleep设置延时来等待go loop()执行,这种做法可行,但是显然是不科学的,如果我的go loop()执行很快结束了,而main函数还在等待,这显然是一种资源上的浪费。

那么如何解决的,我们可以用下面的信道来解决这个问题

func main() {

go loop()

loop()

time.Sleep(time.Seoncd) //停顿一秒

}

信道

信道是什么?简单的来说就是goruntine之间相互通讯的东西。类似Linux中的管道,用来在多个进程之间共享资源。

先看一下例子

func main() {

var chanel chan int = make(chan int) // 定义信道类型变量 chanel

go func(msg string) {

chanel

}("Ping")

msgStr :=

fmt.Println(msgStr)

}

在上述代码中,我们通过定义chanel变量完成了进程间的消息通讯。

通过存消息和取消息两种方法完成进程间的消息通讯。

通过这种方式我们可以控制进程的结束时间

var quit chan int = make(chan int)

func loop() {

for i := 0; i < 10; i++ {

fmt.Printf("%d ", i)

}

quit

}

func main() {

go loop()

loop()

}

我们通过quit来控制loop()的结束时间点,当quit没有取到消息的时候,进程就会阻塞,main函数也就无法继续执行。

如果不用信道来阻塞主线的话,主线就会过早跑完,loop线都没有机会执行、、、

其实,无缓冲的信道永远不会存储数据,只负责数据的流通,为什么这么讲呢?

从无缓冲信道取数据,必须要有数据流进来才可以,否则当前线阻塞

数据流入无缓冲信道, 如果没有其他goroutine来拿走这个数据,那么当前线阻塞

简单来说就是必须有消息流入,并且有消息流出,缺一不可,不然会造成死锁

后续

下一篇博客将会介绍一下死锁以及等待多goruntine的方案