JAVA之线程并发

最近表示被各种并发情况搞的无比蛋疼又神伤,加之在搞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 块。 
1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如: 
public synchronized void accessVal(int newVal); 
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能

执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行

状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有

一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)

。 
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成

员变量的访问。 
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为

synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可

以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供

了更好的解决办法,那就是 synchronized 块。 
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下: 
synchronized(syncObject) { 
//允许访问控制的代码 

synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机

制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。  

 

 博主自己也是测试了很多代码在线程锁这里,总之这里是一个繁琐的过程,由于本身程度不高,JVM没有研究过,大一也没有看过操作系统原理,只能半路出家,试着理解,如果有错误还请大家多多指教。

 

推荐几个博客   http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html就是上边线程锁的转载地址,里面有好多例子,篇幅原因没有转载,大家可以去看看,自己测试一下

                        http://ifeve.com       一个并发编程的网站,是博主的某一届未曾谋面的大神学长在搞的一个网站,由于是比较专业的并发编程问题,所以我们这种渣渣还是早早退散了OTZ

 

/**求知对我们而言最根本的,也许不是为了让我们变得更加高级,对人生报更多奢望——而是为了让我们更自由。只不过要想真正在知识里看到自由,需要恒久的努力与谦卑,以及不管懂了多少依然充满了对这个世界的好奇心

我早有觉悟*/

 

 


  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值