在现在这种情况呢,几乎所有的程序都要求高并发,高可用,那到底什么是并发呢?就让俺给你简单讲讲什么是并发。以及其在Go语言中的实现。(以下的文章是带有味道的文章,小心食用!)
并发是什么?
大家都有过带薪拉屎的经历,公司越大,基本上坑位也就越多,假如公司有1000人,总不能要1000个坑位吧。假如我这1000人要同时拉屎,一起拉屎,那是并发拉屎吗?不,并不是,那叫做并行拉屎。假如一天1000人要拉屎,那我可能100个坑位就够了,能满足1000人/天的QPS拉屎量,这个东西叫并发。
什么是并发安全?
又有人说了,那我可以准备一个大坑位,大家1000人一起拉,先不谈那个坑位要多大。假如公司需要按照每个人拉的屎付清洁费,大家都对这个坑位进行拉屎操作,也就是专业说法中的写操作,有些人屎比较稀啊,流到了其他人的地方,这其他人绝对不乐意了啊,就变成了一种屎竞争(date race),也就是你拉的屎影响到了我拉的屎,导致我需要多付清洁费。这可是会打架的啊!
而且一堆人一起,直接看到了别人的腚,那多不安全(♂)啊!这就是并发不安全,怎么让他安全呢?假如就一个坑位,你不想别人干扰你拉屎,你不就应该把别人阻挡在外面等你拉完再让他拉吗?所以好多厕所坑位都有门锁,有没有道理。通过这样的手段就保证了拉屎安全,也就是并发安全。
其实总的来说,并发编程就是为了保证并发安全进行的编程,想并发开线程就行,或者协程,在多个线程下保证并发安全才是并发编程要解决的事情,后续就会讲述在Go语言中的并发包以及一些并发操作的基本理论。
进程,线程,协程
要讲并发,就离不开进程,线程,协程。这三个东西到底是什么呢?一般人会怎么说?
进程是资源分配的最小单位,线程是CPU调度的最小单位,协程是用户形态的线程,相当于轻量级线程
太俗了!!!太抽象了!!!
我们来点高雅的说法:
进程:上班的一家家公司,里面的资源什么的给线程共享,这家公司倒了基本上不会影响其他公司。
线程:公司里的人,在公司用公司的资源干活,假如拉屎的话,也就是执行拉屎任务的人(线程),这个线程拉屎不冲,也会影响到其他的线程。
协程:可不是Goroutine啊,可以想象成耗费资源少的人,也就是机器人,可以通过设定跟线程做一样的事情,但是就是比线程轻量。
当然在Go语言中,协程就是Goroutine。一般在后面说的线程你也可以直接当成Goroutine。
Go语言中的并发原语
拿常规的并发拉屎流程来说吧,首先你要有门锁吧,也就是 Mutex ,最基本的就是上锁,拉屎,拉完解锁让下一个拉屎。
是不是有时候会遇上检查卫生的?一个队来检查卫生总不能一个个进坑位看吧,当然得大家一起看,所以这个场景就会出现读写锁 RWMutex 。
有时候一堆人一起去厕所拉屎,扫地阿姨得等他们拉完才可以进去扫地吧?总不能把排队的人都赶走吧?所以为了等待这些人拉完屎,然后扫地阿姨进去扫地,就会出现 WaitGroup 等待队列这种情况吧。
为了预防扫地阿姨没扫完出去喝了口水,想回来接着扫却发现厕所又有人的情况,当然就需要出现扫地阿姨扫完了通知大家的情况,所以就有 Cond ,等厕所扫完了,通知大家可以继续拉屎了,不然就不让大家拉屎了。
当然,你厕所只需要建一次就好,所以在Go中还有个 Once 代替了之前的单例模式,用来创建厕所。
当然还有杂物间,要用的时候拿出来,不用的时候放回去的 pool ,以及为了满足PDD上厕所打卡所设立的KV结构类型 sync.Map。
这上面这些东西后续的文章都会十分的营养生动的讲述出来,从例子,到源码,到应用,都会一一描述。敬请期待。