微课讲稿-Java多线程的临界资源_第1页
微课讲稿-Java多线程的临界资源_第2页
微课讲稿-Java多线程的临界资源_第3页
微课讲稿-Java多线程的临界资源_第4页
微课讲稿-Java多线程的临界资源_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java多线程的临界资源北京信息职业技术学院|林志红Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青上节课我们学会了如何写线程,当一个程序启动了一个以上的线程之后,该程序就由原来的单线程程序变成了多线程程序,这些线程并发执行去完成一些复杂的功能。Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青既然是多个线程并发执行,就必然存在线程间的相互制约问题,也就必然存在多线程运行的一些规则,如果不能正确处理线程间的关系,违反了某些重要规则,那么多线程不但不能提高工作效率,相反还会带来严重的问题。Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青多线程并发执行中的重要概念—临界资源我们来看一个例子:例:假设有10张车票,设计两个线程同时出售车票,每售出一张票,都打印剩余票数,如果票已售完,则打印“票已售完!”Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青出售车票问题是一个典型的多线程问题,售票大厅一般都有多个窗口,每个窗口实际上都对应一个售票线程,每卖出一张票,剩余车票就会减去一张。为了简化问题,我们只考虑两个窗口的情况。程序很简单,启动两个线程,这两个线程执行相同的算法,就是不停地将剩余车票减一,直到无票可卖为止。主程序代码如下图:Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青Java多线程的临界资源Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青在上面这个程序中,我们定义了一个Runnable实现类Sell,在这个类中设定了一个变量Ticket_num用于存放初始总车票数,并实现了作为线程体的run方法,在run方法中,对总车票数循环减一,每减一次,将剩余票数打印出来,总车票数已经为零,则打印无票,跳出循环,线程结束。这里用到了一个方法调用Thread.currentThread().getName(),这个调用的功能是取得当前运行的线程名称,这个线程名称是系统给定的,每个线程都有一个不同的名称。Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青在主程序中,创建了Sell类的对象s,并以s为参数,创建了两个线程t和t1,由于t和t1在创建时使用了同一个参数s,所以t和t1的线程体实际上是同一个run方法,也就是说无论是t得到运行机会还是t1获得运行机会,都会去修改同一个s中的Ticket_num变量。两个线程启动后,运行结果如下图所示。这里Thread-0和Thread-1是系统给定的两个线程名称,从结果可以看出,两个线程分别卖出了一些票,剩余车票逐渐下降,直到无票可卖。结果似乎合理!Java多线程的临界资源Java多线程的临界资源问题:该程序有没有潜在的问题?什么是潜在的问题?潜在的问题就是表面上看一切正常,但是有可能在某一时刻突然出现问题,而且这种问题可能还很难复现,这是一种最令人头痛的问题。Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青我们来观察一下上面的程序代码,这段代码非常简单,似乎找不出什么逻辑上的漏洞,运行结果也是合理的。事实上,这段代码是有问题的,这个问题充分体现出多线程与单线程在程序设计思路上的不同。Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青单线程程序,只要保证代码处理逻辑正确即可多线程程序,不但要保证代码处理逻辑正确,而且要保证时序逻辑正确那么什么是时序逻辑呢?这就要回顾一下前面关于线程调度的知识了。回顾旧知人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青在java技术中,线程通常是抢占式的。抢占式调度模型就是许多线程处于可以运行状态(就绪状态),但实际上只有一个线程在运行。该线程一直运行到它终止、阻塞或进入可运行状态(就绪状态),或者另一个具有更高优先级的线程变成可运行状态。在后一种情况下,低优先级的线程被高优先级的线程抢占,高优先级的线程获得运行的机会。回顾旧知人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青所以一个线程体并不是一次完成其运行,而是与另外的线程体交替运行的。正是这种交替运行有可能带来一些问题。

为了说明这个问题,我们可以把本例的线程体简化一下,只保留核心部分如下图所示:Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青回顾旧知人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青我们知道,我们所创建的两个线程都是用的这段代码,如果用红色代表线程1,用黄色代表线程2,那么线程1和线程2可以如下表示.这里之所以把线程体由一个整体变成用一些语句碎片来表示,实际上是为了更真实地反映线程的生存状况。现在假设Ticket_num=1,也就是还剩最后一张票了,我们来分析一下线程的运行情况:Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青线程1:线程2:Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青情况1:初始条件:Ticket_num=1在这种情况下,线程1判断Ticket_num大于0,将Ticket_num减1后将打印:线程1:剩余车票0线程2判断Ticket_num已经不大于0,所以打印:线程2:无票!Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青情况1,调度器按如图方式调度:运行结果为:线程1:剩余车票0线程2:无票!这个结果从逻辑上看是正确的,但是从真实情况来讲,这个结果并不是总能得到。因为这种调度情况并不是总能重复,线程1执行完毕,然后线程2执行,这实际上已不是线程的并发执行,而是线程的串行化执行。Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青情况2:初始条件:Ticket_num=1线程1:判断Ticket_num大于0,应该将Ticket_num减1,但此时CPU切换到线程2线程2:因为线程1还没有来得及将Ticket_num减1,所以Ticket_num仍然为1,所以此时线程2判断Ticket_num大于0,将Ticket_num减1后打印“线程2:剩余车票0”后CPU切换回线程1线程1:继续执行Ticket_num减1语句,但是此时Ticket_num减1操作已被线程2执行过一次,所以Ticket_num的值已经为0,所以线程1执行完Ticket_num减1操作后,Ticket_num的值变为-1,所以线程1打印“线程1:剩余车票-1”Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青情况2:调度器按如图方式调度运行结果为:线程2:剩余车票0线程1:剩余车票-1这个结果明显不合理,剩余车票出现了负数,说明车票卖光了以后又卖出了一张车票。

所以我们可以看到,调度策略的不同可能会导致多线程运行结果的不同。Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青现在我们来模拟一下这种情况,线程在某一个时刻被剥夺了运行权,在某一时刻又恢复了运行。将前面的代码略微修改如图所示。我们在判断剩余票数大于零之后插入了一条语句:Thread.currentThread().sleep(100);这条语句的功能是线程休眠100毫秒,意思是线程放弃CPU,100毫秒后回到就绪状态等待调度重新进入运行状态。这实际上是模拟了该线程在这一时刻被剥夺运行权的情况。Java多线程的临界资源Java多线程的临界资源人生之路是漫长的,但紧要处只有几步,尤其当人年轻的时候。

——柳青我们来看一下运行结果,如下图所示。出现问题了,剩余车票数为-1,多卖出去了一张票!Java多线程的临界资源学习指导临界资源为了进一步解释这个现象,我们引入一个新的术语:临界资源。多个线程间共享的数据称为临界资源。由于是线程调度器负责线程的调度,程序员无法精确控制多线程的交替顺序。这种情况下,多线程对临界资源的访问有时会导致数据的不一致。学习指导对于这个例子来讲,剩余车票数就是两个线程都要访问的临界资源。当还剩最后一张票的时候,假设线程1获得运行权,此时首先判断剩余票数是否为0,不为0则执行票数减1操作。然而如果在减1操作执行之前,CPU使用权因某种原因转到了线程2,因为线程1的减1操作还没有执行,所以线程2所看到的票数也不为0,所以线程2会将总票数减1,此时总票数已经为0。线程2运行结束后,CPU使用权回到线程1,此时线程1继续前面的操作,将总票数减1,然而此时总票数已经被线程2减为0,所以线程1操作

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论