最近表示被各种并发情况搞的无比蛋疼又神伤,加之在搞socket通信这种中下层玩意,简直日渐憔悴。嗯不过每一次走得更高更远都是一个浪漫和内涵的故事,所以这次来把并发搞搞清楚
首先来说一个老生常谈的问题
并发并行的区别,然后再说说进程和线程的区别,已然看到无数学长学姐笔试面试碰到这种题
以下大多出自互联网,如有错误求大神指正
先来说并发并行
由于这篇文章转载太广。。。我着实不知道到底哪个是原文。。。就昧着良心盗用下图片。。。
这是一只立志把JAVA并发编程的书都送进火堆烧掉的老鼠。。。我们假设一个火堆烧掉左边一大堆书需要10秒,则如果不算老鼠运输时间,烧书只要10秒完成
现在我们加倍,两堆书两只老鼠两个火堆,可以预见,左边两堆书两个火堆烧,去掉老鼠运输时间,则烧书还是只要10秒。
那么这种情况呢,两堆书两只老鼠一堆火,如果只计算烧书时间,那么可以知道两堆书一堆火要20秒,就是说无论两只老鼠的运输效率怎么高,管理模式怎么科学,烧掉这些蛋疼的书还是最少要20秒。
从上面两种情况可以看出,两堆火两堆书,这就是并行,两堆书一堆火,这就是并发。
而如我们所见,烧书的过程不只是火在烧,还有老鼠在运输,如果每次老鼠运输的书是书堆的1/10,即火烧要1秒,但是他来去都要2秒,即来回要4秒。
两堆火两堆书的情况是 两只老鼠同时开始同时结束,各跑了9个半来回(最后一次运到就好),用了38秒。
一堆火两堆书的情况是 一只老鼠运到火堆时另一只开始运,则两只老鼠交替,两只老鼠也都是各跑了9各半来回,但由于有先后次序,第一只开始后两秒两只才一起运输起来,则一共要40秒
(卧槽博主的逻辑要爆了感觉尤其是连续写了12小时代码以后!!!如果你发现博主的逻辑错了,没问题,博主现在连博主是人这种简单命题都开始怀疑了,简直就是代码机器!!!)
所以可见,一个火堆和两个火堆的最后效率是基本差不多的,怪不得那些MBA的挣钱要比程序猿高!!!这里就牵扯到系统什么时间片划分什么什么的balabala
PS注:上面除了第一幅第二幅图为盗用。。。其他文字和第三幅图都是我手写和手PS的,如果作者看到觉得侵犯了你的权益请先联系我立马删除。。。(好吧负罪感大大减轻)
以上就是并发和并行的区别,换句话说,就像一个人(cpu)喂2个孩子(程序),轮换着每人喂一口,表面上两个孩子都在吃饭,其实同时只有一个孩子在吃饭。并行,就是2个人喂2个孩子,两个孩子也同时在吃饭。
再来说进程与线程
摘自:http://ifeve.com/java-concurrency-cookbook/ 进程是以独立于其他进程的方式运行的,进程间是互相隔离的。一个进程无法直接访问另一个进程的数据。进程的资源诸如内存和CPU时间片都是由操作系统来分配。
线程又被称为轻量级进程。每个线程有它独自的调用栈, 但是在同一进程下的线程又能互相访问它们间的共享数据。每个线程都有它独自的缓存。如果一个线程读取了某些共享数据,那么它将这些数据存放在自己的缓存中以供将来再次读取。
一个JAVA应用程序默认以一个进程的形式运行着。在一个JAVA程序中,你将协同多个不同的线程一起完成并行运算或实现异步行为。 |
我们可以把进程类比为一个工厂车间,它代表CPU所能处理的单个任务,为了方便我们处理,假设由于工厂(CPU)电力有限,同时只能保证一个车间运作,即一个CPU一次只运行一个进程,而不是什么时间片什么balabala我也不太懂。。。
好。。。车间是一个进程,一个车间里面有很多工人,他们协同完成一个任务,(注意我这里可以避开了说他们在一起同时工作,因为这里不是一个并发过程),车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。
而如果你从你们车间跑到别的车间去,就会发现门口一个大牌子上面写着“闲人免进”,好了闲人回到你的车间。。。这象征一般进程间是不共享数据的。
以上是进程和线程的区别。
这里有一个有意思的现象,你在车间里相当于一个线程,每个线程可以共享内存数据,好,厕所是车间里的一个数据,你可以使用,别人也可以使用,好,然后大家一起使用,好,然后大家同时使用。。。这不太好吧。。。但是确实线程是可以同时使用数据的啊。
这里就会牵扯到一个线程锁的问题
摘自http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。 执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行 状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有 一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized) 。 员变量的访问。 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可 以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供 了更好的解决办法,那就是 synchronized 块。 制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。 |
博主自己也是测试了很多代码在线程锁这里,总之这里是一个繁琐的过程,由于本身程度不高,JVM没有研究过,大一也没有看过操作系统原理,只能半路出家,试着理解,如果有错误还请大家多多指教。
推荐几个博客 http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html就是上边线程锁的转载地址,里面有好多例子,篇幅原因没有转载,大家可以去看看,自己测试一下
http://ifeve.com 一个并发编程的网站,是博主的某一届未曾谋面的大神学长在搞的一个网站,由于是比较专业的并发编程问题,所以我们这种渣渣还是早早退散了OTZ
/**求知对我们而言最根本的,也许不是为了让我们变得更加高级,对人生报更多奢望——而是为了让我们更自由。只不过要想真正在知识里看到自由,需要恒久的努力与谦卑,以及不管懂了多少依然充满了对这个世界的好奇心
我早有觉悟*/