我们都知道,经过多年的发展和无数Java开发者的不懈努力,Java已经由一门单纯的计算机编程语言,逐渐演变成一套强大的以及仍在可持续发展中的技术体系平台。
虽然,Java设计者们根据不同的技术规范,把Java划分为3种结构独立且又彼此依赖的技术体系,分别是Java SE,Java EE 以及Java ME,其中Java EE 在广泛应用在企业级开发领域中。
除了包括Java API组件外,其衍生和扩充了Web组件,事务组件,分布式组件,EJB组件,消息组件等,并且持续发展到如今,其中,虽然有许多组件现如今不再适用,但是许多组件在我们日常开发工作中,扮演着同样重要的角色和依旧服务着我们日新月异的业务需求。
综合Java EE的这些技术,我们可以根据我们的实际需要和满足我们的业务需求的情况下,可以快速构建出一个具备高性能,结构严谨且相对稳定的应用平台,虽然现在云原生时代异军突起许多基于非Java的其他技术平台,但是在分布式时代,Java EE是用于构建SOA架构的首先平台,甚至基于SpringCloud构建微服务应用平台也离不开Java EE 的支撑。
个人觉得,Java的持续发展需要感谢Google,正是起初Google将Java作为Android操作系统的应用层编程语言,使得Java可以在PC时代和移动互联网时代得到快速发展,可以用于手持设备,嵌入式设备,个人PC设备,高性能的集群服务器和大型机器平台。
当然,Java的发展也不是一帆风顺的,也曾被许多开发者诟病和嫌弃,但是就凭Java在行业里能否覆盖的场景来说,对于它的友好性和包容性,这不由让我们心怀敬意。其中,除了Java有丰富的内置API供我们使用外,尤其Java对于并发编程的支持,也是我们最难以释怀的,甚至是我们作为Java开发者最头疼的问题所在。
虽然,并发编程这个技术领域已经发展了半个世纪了,相关的理论和技术纷繁复杂。那有没有一种核心技术可以很方便地解决我们的并发问题呢?今天,我们就来一起走进Java领域的并发编程的核心——Java线程机制。
基本概述
正在上传…重新上传取消
在Java中,对于Java语言层面的线程,我们基本都不会太陌生,甚至耳熟能详。但是在此之前,我们先来探讨一下,什么是管程技术?Java 语言在 1.5 之前,提供的唯一的并发原语就是管程,而且 1.5 之后提供的 SDK 并发包,也是以管程技术为基础的。除此之外,其中C/C++、C# 等高级语言也都支持管程。
关于管程
管程(Monitor)是指定义了一个数据结构和能为并发进程所执行的一组操作,这组操作能同步进程和改变管程中的数据。主要是指提供了一种机制,线程可以临时放弃互斥访问,等待某些条件得到满足后,重新获得执行权恢复它的互斥访问。
所谓管程,指的是管理共享变量以及对共享变量的操作过程,让他们支持并发。翻译为 Java 领域的语言,就是管理类的成员变量和成员方法,让这个类是线程安全的。
基本定义
首先,系统中的各种硬件资源和软件资源均可用数据结构抽象地描述其资源特性,即用少量信息和对该资源所执行的操作来表征该资源,而忽略它们的内部结构和实现细节。
其次,可以利用共享数据结构抽象地表示系统中的共享资源,并且将对该共享数据结构实施的特定操作定义为一组过程。进程对共享资源的申请、释放和其它操作必须通过这组过程,间接地对共享数据结构实现操作。
然后,对于请求访问共享资源的诸多并发进程,可以根据资源的情况接受或阻塞,确保每次仅有一个进程进入管程,执行这组过程,使用共享资源,达到对共享资源所有访问的统一管理,有效地实现进程互斥。
最后,代表共享资源的数据结构以及由对该共享数据结构实施操作的一组过程所组成的资源管理程序共同构成了一个操作系统的资源管理模块,我们称之为管程,管程被请求和释放资源的进程所调用。
综上所述,管程(Monitor)是指定义了一个数据结构和能为并发进程所执行的一组操作,这组操作能同步进程和改变管程中的数据。主要是指提供了一种机制,线程可以临时放弃互斥访问,等待某些条件得到满足后,重新获得执行权恢复它的互斥访问。
基本组成
由上述的定义可知,管程由四部分组成:
- 管程的名称;
- 局部于管程的共享数据结构说明;
- 对该数据结构进行操作的一组过程;
- 对局部于管程的共享数据设置初始值的语句
实际上,管程中包含了面向对象的思想,它将表征共享资源的数据结构及其对数据结构操作的一组过程,包括同步机制,都集中并封装在一个对象内部,隐藏了实现细节。
封装于管程内部的数据结构仅能被封装于管程内部的过程所访问,任何管程外的过程都不能访问它;反之,封装于管程内部的过程也仅能访问管程内的数据结构。
所有进程要访问临界资源时,都只能通过管程间接访问,而管程每次只准许一个进程进入管程,执行管程内的过程,从而实现了进程互斥。
基本特点
管程是一种程序设计语言的结构成分,它和信号量有同等的表达能力,从语言的角度看,管程主要有以下特点:
- 模块化,即管程是一个基本程序单位,可以单独编译;
- 抽象数据类型,指管程中不仅有数据,而且有对数据的操作;
- 信息屏蔽,指管程中的数据结构只能被管程中的过程访问,这些过程也是在管程内部定义的,供管程外的进程调用,而管程中的数据结构以及过程(函数)的具体实现外部不可见。
基本模型
在管程的发展史上,先后出现过三种不同的管程模型,分别是:Hasen 模型、Hoare 模型和 MESA 模型。其中,现在广泛应用的是 MESA 模型,并且 Java 管程的实现参考的也是 MESA 模型。
接下来,我们就针对几种管程模型分别来简单的说明一下,它们之间的区别。
假设有这样一个进程同步机制中的问题:如果进程P1因x条件处于阻塞状态,那么当进程P2执行了x.signal操作唤醒P1后,进程P1和P2此时同时处于管程中了,这是不被允许的,那么如何确定哪个执行哪个等待?
一般来说,我们都会采用如下两种方式来进行处理:
- 第一种方式:假如进程 P2进行等待,直至进程P1离开管程或者等待另一个条件
- 第二种方式:假如进程 P1进行等待,直至进程P2离开管程或者等待另一个条件
综上所述,三种不同的管程模型采取的方式如下:
1.Hasen 模型
Hansan管程模型,采用了基于两种的折中处理。主要是规定管程中的所有过程执行的signal操作是过程体的最后一个操作,于是,进程P2执行完signal操作后立即退出管程,因此进程P1马上被恢复执行。
2.Hoare 模型
Hoare 管程模型,采用第一种方式处理。只要进程 P2进行等待,直至进程P1离开管程或者等待。
3.MESA 模型
MESA 管程模型,采用第二种方式处理。只要进程 P1进行等待,直至进程P2离开管程或者等待。
基本实现
在并发编程领域