北京java培训多少钱 图解Java并发

栏目:常见问题丨时间:07-11丨来源:未知丨作者:光环IT学院
  北京java培训多少钱 图解Java并发。既然聊并发,我们首先会思考为什么要引入这个技术。通常写程序,我们习惯用单线程串行的思维理解程序运行,编写业务逻辑(实际上我们通常的代码并不是按顺序串行执行的,只是看上去像,as-if-serial)。这样可以减少复杂度,也便于测试,往往当需要性能提升,我们才会想到使用并发。那么为什么要并发呢?

  接下来,我尝试系统、深入、图文并茂的聊聊并发、JSR133中定义的JMM以及其中具体的语义细节。


北京java培训学费
  充分利用CPU资源

  首先,并发可以充分利用CPU资源。简单来说就是在多核处理器广泛使用背景下,如果我们的程序还是单线程串行的运行,会对硬件资源浪费。比如有一个8内核的CPU,单线程对CPU的损耗不会超过1/8。这对硬件的使用明显是巨大浪费。

  一个监控示例:只有一半的CPU资源得到了利用

  更重要的是,(目前)CPU的运行速度比(磁盘读写、网络IO等)通信、存储子系统快几个数量级,我们单纯地串行处理任务,CPU的速度即使再快,也会因为其他子系统的速度过慢,而不得不较长时间“陪同”(如,大量时间花在IO上),浪费CPU资源。多线程可以针对这种情况,更大程度的利用(因通信、存储子系统过慢)闲置的CPU资源。

  也就是说我们不能指望程序自发的充分利用CPU资源,我们完全可以在CPU被空闲时(如,时间全部花在IO上)充分利用它,去做更多的事情。

  以下是一个小程序,用来模拟上文所说内容:

  更快、更好的体验

  比如用户在手机上下单去贷款申请,它包括插入申请数据、个人信息审核、金融信誉审核、其他审核、发送邮件通知,生成分期账单等等。用户贷款申请,需要这些流程都完成,才能保证贷款申请流程完毕。如何能让这些流程更快执行呢?

  答案很多,但并发肯定是最有效的一个。使用并发技术、对数据弱一致性的业务并行处理或者异步处理,缩短响应时间,提升用户体验。

  我们都知道,线程在java中是最小的独立执行单元,我们通过Thread类去抽象每个线程个体。并发(Concurrency)就是让多个线程同时执行,每个线程作为一个独立的执行单元去完成任务。

  上文已经讨论了使用并发技术的益处,但每个硬币都有两面,并发技术也不例外,在给我们带来益处的同时,也存在一些风险需要去谨慎注意:

北京java培训学费
 
  并发的风险

  创建线程

  每个线程的创建都需要占用多种资源如内存、CPU等等。

  举例来说,之前参与过的垂直架构的实时计算应用(OTA行业的价格计算中心,每天计算量达到100亿次),虽然不对外提供任何http服务,但发现tomcat默认启动了http数百个线程(http线程池),这很明显就是一种因过度创建线程产生的性能浪费。

  上下文切换

  多线程运行中,CPU会给线程分配时间片,也就是轮流占用某个CPU。

  这样就会产生上下文切换——也就是保留当前线程状态,切换到下一个线程,下一个线程加载自己上次的状态,继续运行——从保存当下状态到下次再加载后运行的过程就是一次上下文切换。

  上下文切换也会对系统造成额外的消耗,主要原因就是每次上下文切换都需要额外的时间去"恢复现场"与"保存现场"。

  更复杂,有挑战

  并发编程比串行的编程更加复杂,要考虑锁问题、线程安全、重排序问题、共享数据的一致性、线程池的设置等等。

  理解并发

  简单来说,理解并发就是要理解多线程之间的通信与同步。

  前不久有朋友说掌握好java并发就“是Thread、Runnable、以及线程池相关类的API,都已经做好了,直接使用就行…技术不要研究太深…..”。这难道不是一种技术上的浮躁?

  线程间通信

  所谓线程间通信就是线程间相互沟通,也可以叫做握手、交互。

  java中可以通过共享内存实现通信,但也不局限于内存,也可以是可共享的任何数据。

  举例来说:比如,线程A需要让线程B修改某些属性然后执行,那么线程A该如何告诉线程B自己的需求呢?

  更具体地说:

  线程A-action:更新某个变量,然后将这个更新的变量刷入主存中去。

  线程B-action:会到主存中获取这个线程A更新过的共享变量。

  这两个步骤就完成了一次通信。

  实质就是线程A向线程B发送了包含更新数据的消息,这种通过共享主存的通信方式是隐式的通信(java采用隐式通信),还有消息传递的并发模型通过直接发送消息通信。

  线程间同步

  多线程正确的同步[1]指的是多个线程有序的执行线程任务,以完成一个共同的目标或者执行一系列有序的动作。

  [1]有些文章用词为——“错误地同步”(incorrectlysynchronized)、“未完成地同步”(incompletelysynchronized)或“没有同步”(withoutanysynchronization、nosynchronization),这些词含义都是一样的。所以本文统一用词为“正确的同步”或者“错误的同步”,以避免读者困扰。

  确保三个线程按照一定顺序操作共享资源(对共享资源操作的代码区称为临界区)

  换句话说,正确的同步就是保证按照正确的顺序让线程运行并完成通信,类似现实生活中的红绿灯,如果没有红绿灯,后果可想而知。

  在java中通过使用volatile、synchronized关键字、以及JDK提供的并发框架等手段来完成同步(以及通信,线程间通信与同步关系密切),以解决因为同步产生的竞争状态问题。哲学家进餐问题、读写者问题,生产消费者问题都是同步的经典问题,为了加深理解,值得一读。

  什么是错误的同步

  参考JSR相关文档,总结如下,当我们在java并发编程中谈到“错误同步”的代码,我们是指这样的一些代码:

  线程A执行一个变量的写操作;

  线程B执行这个变量的读操作;

  这两个操作没有被正确的同步处理,也就是说他们执行的先后顺序是不确定的。

  当出现了以上类似情况我们通常称在这个变量上存在“数据竞争”(adatarace)。一个存在数据竞争的程序都是没有正确同步过的程序,存在隐患。

  JMM

  JMM(Javamemorymodel,通常说的是在JSR133中确定的JMM)定义了什么样的行为在java多线程中合法。详细规范了线程之间如何通过内存实现通信,以及通信的具体细节;还有程序中变量之间的关联,以及这些变量如何在寄存器、缓存、主存上被读\写的细节。

  简单来说,通过一些并发细节的规范、约束,对线程之间的通信\同步规则做了完整、详细的描述,并且屏蔽了操作系统以及硬件的底层细节,抽象出一个跨平台的内存模型(JMM),以便程序员可以更高效、准确使用JAVA进行并发编程。

       原创文章,转载请注明出处:光环it学院

光环IT学院,专注IT培训16年,培养IT行业精英! —

光环IT学院

注:本站文章采用原创+网络转载两个方式,对于转载的文章,由于网络信息过多,无法100%找到原始出处。如果本站文章有侵犯了您的权益,请联系我们删除或授权。

请遵守理性,宽容,换位思考的原则

2017-07-11 13:10 发布 丨 人浏览

热点推荐

微信
公众号

微信扫码,即可关注

反馈
意见
回到
顶部