一起玩转java并发(1)背景

为什么需要并发编程


其实,作为要搞后台研发的童鞋们,不管你是搞java,还是搞其他语言的,我们都会或多或少接触(再不济也听说过吧)并发编程。那问题来了,我们为啥要用并发编程?能不用吗?

我知道,就说刚上面那段话,有的同学就已经有晕的地方了(毕竟都是过来人)。那就是什么是并发?并行又是啥?你就这么理解。现在有三个小盆友,如果有三个棒棒糖,大家自己舔自己的,那就是并行(并肩行走)。如果只有一个棒棒糖,大家轮着舔,一人舔一口,那就是并发。(我要吐了……)。并行主要用于多核编程中。

我们当然可以不用并发编程,也能让程序运行起来。那我们为啥还要用呢?我们首先看看现实生活中的一个典型并发的场景,然后再来回答这个问题。

大家都有买过奶茶。现在路边有一个奶茶店。奶茶店的操作流程是:最前面是柜台,站着奶茶妹妹。你去买奶茶的时候,走到奶茶妹妹面前说:我要喝强东丝袜奶茶(再吐……)。奶茶妹妹听到后,在机器上好单后,转身给后面的员工说:做一杯子丝袜奶茶。后面的员工听到后,就开始准备奶茶了。然后奶茶妹妹对你说:“请您稍等。下一位~”……

上面的场景就是一个典型的并发场景。从上个场景中,我认为并发主要有以下三个好处:

1 .更好的编程模型

假如我们现在要在程序中描述上面那个场景,你能先想一下,如果不用并发多线程的方式,用普通单线程的方式,应该怎么描述呢?给你三秒钟思考。好了,看到这儿三秒就结束了。是不是觉得描述起来还是比较麻烦的。那我们如果用多线程的方式描述呢?
看看用多线程描述:

其实在上述的场景中,奶茶店就是我们的服务器后台。我们把每个店员都定义成一个线程。一个线程(店员)在前面接受请求(奶茶妹妹)。接收到后把请求转发给其他线程去做具体的操作,然后那个线程继续等待请求。而具体的操作线程会去执行具体的处理(做奶茶)。

可以看到,当我们使用并发多线程的时候,很自然地就把上面的场景描述清楚了。因此,并发多线程编程提供了一个较好的编程模型。

2.更高的资源利用率

在上面的场景中,假如我们有很多器具。如果只有一个店员A,那么就只能先招呼顾客,知道了顾客的需求后,A再转身去做奶茶。这时候柜台那边就没人了,有新的顾客来,就只能等着。当A做完奶茶后,A再回来到柜台招呼顾客,那后台的操作就没人操作了。这样使得不管是柜台,还是后台做奶茶的机器,都没有得到充分利用。
而并发多线程,能够更高利用率地利用店里的资源,有店员一直在柜台站着,有店员一直在用奶茶机做奶茶,这样资源的利用率会大大提升。

3.更快的程序运行速度

这个运行速度,并不是指程序会运行的更快。直观地说,比如说奶茶店里只有一个员工。收钱,做奶茶都是他。那作为顾客,是不是等待的时间就会比较长。假如店里有很多员工,收钱、做奶茶都分别有员工,那等待的时间相对就会更短。

因此,我们需要在后台使用并发多线程编程。

并发编程有哪些挑战


那既然我们要使用并发编程了。那并发编程的时候,会有哪些挑战呢?既然多线程能够提高资源利用率,加快处理速度,那么我是不是就开线程开的越多越好呢?其实不是的。在并发编程中,主要会存在以下三方面的考虑:

上下文切换

我们知道, CPU是分时复用的。在单核处理器中(多核也存在),如果我们使用了多线程,不同的线程在不同的时间占用CPU,那么就肯定会做线程之间的切换。
好,那线程切换会有什么问题呢?其实相对于串行,多线程会增加两个额外的开销:

线程的生命周期管理时间(如创建、删除等),以及上下文切换的时间(保存现场等操作)。

当线程数量较多时,这两部分的时间开销会很大,会造成多线程反而比单线程更慢。我们可以通过vmstat查看线程中的上下文切换次数,来看是否切换过多。
当然减少上下文切换,也是有很多方法的。比如采用无锁并发编程、CAS、协程等等。具体细节后面再说。

死锁

这个问题是多线程中的典型问题。有一些资源,只能单线程访问,我们叫临界资源。我们为了防止多线程同时访问那个数据,造成数据不一致问题,所以我们要做线程同步,也就是控制各个线程如何访问那个资源。做线程同步的时候,假如我们没注意,就可能出现死锁。
最典型的例子,就是线程A需要资源X,Y。此时线程A已经获得了资源X,但是需要Y。但是Y现在被别人占用了,因此A就等着Y可用。线程B也需要X,Y。此时B占用了Y,但是需要X,但是X此时被A占用了,因此B也等着X可用。这时候,A占用X,还需要Y。B占用Y,还需要X。这俩傻孩子就相互等着了,这也就成死锁了。
解决死锁的方式有很多,如果你学过操作系统的话,就能知道解决的思想了。死锁避免、死锁监测、死锁预防、鸵鸟方法等都是可以处理的。

资源限制

这个问题也比较容易理解。就是说,在上面的奶茶店场景中,我的店就只有那么大,假如就20平米。这时候就算你给我50个店员,我店也就那么大。可能不仅没法提高处理速度,反而大家手忙脚乱,速度反而还慢了。在计算机中,也就说受限于IO,存储、处理器等等。
解决方式也很直观。第一就是:既然店小,那就开分店,把员工分出去。也就是用分布式思想处理。第二就是资源复用。比如说连接池等等

以上呢,就是基础背景。我们说了为什么需要并发编程,以及并发编程会遇到的问题。其实并发编程中的很大一部分,都是在讲如何具体地处理我们刚才说的问题,遇到问题如何去解决,具体有哪些方法去解决,都是后面要讲的。

猜你喜欢

转载自blog.csdn.net/Snail_Ren/article/details/76572687