温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java管程的概念和实现原理

发布时间:2021-06-18 16:11:39 来源:亿速云 阅读:715 作者:chen 栏目:编程语言

本篇内容主要讲解“Java管程的概念和实现原理”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java管程的概念和实现原理”吧!

管程的概念

在操作系统的概念里,monitor(管程)是为了解决使用信号量同步容易出错的问题,而提出的一种高级同步原语。monitor是编程语言的组成部分,进入monitor时的互斥由编译器来负责,写monitor的人无需关心编译器是如何实现互斥的,只需要将所有临界区转换成monitor即可。尽管管程提供了一种实现互斥的简单方式,但是还不够,还需要一种办法使得进程/线程在无法继续执行时被阻塞,解决的方法是引入条件变量以及两个相关的操作:wait和signal。Java是真正支持管程的编程语言之一。

Java中的monitor支持两种类型的线程同步: 互斥锁同步和协作同步。在Java虚拟机中通过object locks支持的互斥锁,允许多个线程独立地工作在共享数据上,而不会互相干扰(在使用上即synchronized关键字,这里提到的是虚拟机层原理)。Java虚拟机通过Object类的 wait 和 notify 方法支持协作,使线程能够朝着共同的目标协同工作。

互斥锁同步

一个monitor就像一栋楼里面的一个特殊房间,在同一时间内只能被一个线程所占有,这个房间通常包含一些数据,从线程进入这个房间到离开这个房间,它可以访问房间里的任何数据。

  • 进入这栋楼,称为entering the monitor

  • 进入这个特殊房间,称为acquiring the monitor

  • 占有这个特殊房间,称为owning the monitor

  • 离开这个特殊房间,称为releasing the monitor

  • 离开这栋楼,称为exiting the monitor

除了与数据关联之外,一个monitor还被关联了很多的代码,称为monitor regionsmonitor regions包含一段原子的,不可分割的执行的代码。

当线程到达monitor regions的开始位置时,它将被放置到所关联monitor的一个 entry set中。 entry set类似于monitor大楼的前门廊。如果在entry set中没有其他线程在等待,且当前没有其他线程拥有monitor,则线程获取monitor并继续执行monitor regions内的代码,执行完成后,它退出并释放monitor。

如果一个线程到达monitor regions的开始位置时,该monitor已经被另一个线程所拥有,那么新到达的线程必须在 entry set中等待,只有当拥有者退出monitor后,新到达的线程必须与同样在entry set中等待的其他线程竞争,只有一个线程可以胜出并获得monitor。

以上讲述的是互斥锁同步。互斥锁同步是指由多个线程互斥地执行monitor regions ,在任何时候,只有一个线程可以执行特定monitor的monitor regions。一般来说,只有当多个线程共享数据或其他资源时,互斥锁才是重要的。如果两个线程不使用任何公共数据或资源,它们通常不会互相干扰,也不需要以互斥的方式执行。

协作同步

当一个线程需要某些数据处于特定状态,而另一个线程负责将数据转换到该状态时,协作非常重要。例如,一个“写线程”负责填充的缓冲区,一个“读线程”从缓冲区取走数据。如果读线程发现缓冲区为空,则必须等待写线程填充数据。如果写线程发现缓冲区满了,则必须等待读线程取走数据。

Java 虚拟机使用的monitor的形式称为"Wait and Notify" monitor,也可以称为"Signal and Continue" monitor,在这种monitor形式中,当前拥有monitor的线程可以通过执行 wait 命令暂停(suspended)自己,它释放monitor并进入一个wait set。线程将在wait set中保持暂停状态,直到另一个线程在monitor内执行notify命令后。当一个线程执行一个 notify 时,它继续拥有monitor,直到它通过执行一个wait命令,或者执行完成monitor regions内的代码来释放monitor。通知线程释放monitor之后,等待线程将会复活(resurrected)并可以重新获取monitor。

Java管程的概念和实现原理

图中包含3个区域,中心区域包含一个活跃的线程(正在执行的),该线程拥有monitor,可以执行monitor regions内的代码,称之为monitor's owner,左边是一个 entry set,右边是一个wait set。图中有5扇门,线程必须通过这些门与monitor交互。

当一个线程执行到monitor regions开始的地方时,它通过最左边的1号门进入 entry set,如果当前没有线程拥有monitor并且entry set中只有这一个线程,该线程会立即通过2号门成为monitor's owner,该线程可以继续执行monitor regions内的代码。如果当前有其他线程拥有monitor,该线程必须在entry set中等待,这个区域中可能有很多个其他的线程在等待。

图中 entry set中有3个挂起的线程,wait set中有4个,只有当monitor's owner释放了monitor后,这些线程才有机会得到执行。monitor's owner释放monitor有2种方式:

  1. 执行完成区域内的代码,通过5号门退出。

  2. 执行wait命令,进入wait set

如果monitor's owner在释放monitor之前没有执行notify命令,那么只有entry set中的线程会通过竞争来获得monitor。如果执行了notify,那么entry set中的线程将不得不与wait set中线程竞争。如果一个线程从entry set中竞争获胜,它通过2号门,成为monitor的新主人。如果wait set中的一个线程竞争获胜,它通过4号门重新获得monitor。注意,3号门和4号门是线程进入或退出wait set的唯一方式,线程只有在当前拥有monitor的情况下才能执行 wait 命令,而且它不能自动的离开wait set并再次成为monitor's owner

在Java虚拟机中,线程可以选择在执行wait命令时指定一个timeout。如果一个线程指定了timeout,如果在timeout到期之前没有其他线程执行通知,那么等待的线程会收到来自虚拟机的自动通知。timeout过期后,即使没有其他线程执行显式通知,等待线程也会恢复。Java虚拟机提供了两种通知命令: “ notify”和“ notify all”。notify 命令可以从wait set中任意选择一个线程,并将其标记为恢复。notify all命令标记当前处于wait set中的所有线程恢复。

Java中Object类声明了5个方法(wait和notify),使程序员能够使用Java虚拟机对同步协调方面的支持。这些方法被声明为 public 和 final,因此它们被所有类继承,只能从同步的方法或语句中调用它们。换句话说,在调用这些方法中的任何一个之前,必须已经获取与对象关联的锁。

到此,相信大家对“Java管程的概念和实现原理”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI