什么是管程,管程机制及其使用方法详解
虽然信号量提供了一种方便且有效的进程同步机制,但是它们的使用错误可能导致难以检测的时序错误,因为这些错误只有在特定执行顺序时才会出现,而这些顺序并不总是出现。
为了处理这种错误,研究人员开发了一些高级语言工具,一种重要的、高级的同步工具,即管程(monitor)。
管程类型也包括一组变量,用于定义这一类型的实例状态,也包括操作这些变量的函数实现。管程类型的语法如下所示:
管程结构确保每次只有一个进程在管程内处于活动状态。因此,程序员不需要明确编写同步约束(图 1)。
图 1 管程的示意图
然而,如到目前为止所定义的管程结构,在处理某些同步问题时,还不够强大。为此,我们需要定义附加的同步机制;这些可由条件(condition)结构来提供。 当程序员需要编写定制的同步方案时,他可定义一个或多个类型为 condition 的变量:
操作
图 2 具有条件变量的管程
现在,假设当操作
注意,从概念上说两个进程都可以继续执行。有两种可能性存在:
对于任一选项,都有赞同理由。一方面,由于 P 已经在管程中执行,唤醒并继续的方法似乎更为合理。另一方面,如果我们允许线程 P 继续,那么 Q 等待的逻辑条件在 Q 重新启动时可能已不再成立。Concurrent Pascal 语言采用这两种选择的折中。当进程 P 执行操作 signal 时,它立即离开管程。因此,进程 Q 立即重新执行。
许多编程语言,如 Java 和 C#,都采用本节所述的管程思想。其他语言,如 Erlang,提供类似机制的并发支持。
为了处理这种错误,研究人员开发了一些高级语言工具,一种重要的、高级的同步工具,即管程(monitor)。
管程的使用方法
抽象数据类型(简称 ADT)封装了数据及对其操作的一组函数,这一类型独立于任何特定的 ADT 实现。管程类型属于 ADT 类型,提供一组由程序员定义的、在管程内互斥的操作。管程类型也包括一组变量,用于定义这一类型的实例状态,也包括操作这些变量的函数实现。管程类型的语法如下所示:
monitor monitor name
{
/* shared variable declarations */
function P1 (...) {
...
}
function P2 (...){
...
}
.
.
.
function Pn ( . . . ) {
...
}
initialization_code (...){
...
}
}
管程结构确保每次只有一个进程在管程内处于活动状态。因此,程序员不需要明确编写同步约束(图 1)。
图 1 管程的示意图
然而,如到目前为止所定义的管程结构,在处理某些同步问题时,还不够强大。为此,我们需要定义附加的同步机制;这些可由条件(condition)结构来提供。 当程序员需要编写定制的同步方案时,他可定义一个或多个类型为 condition 的变量:
condition x, y;
对于条件变量,只有操作 wait() 和 signal() 可以调用。操作x.wait();
意味着调用这一操作的进程会被挂起,直到另一进程调用 x.signal();
操作
x.signal()
重新恢复正好一个挂起进程。如果没有挂起进程,那么操作 signal() 就没有作用,即x的状态如同没有执行任何操作(图 2 )。这一操作与信号量的操作 signal() 不同,后者始终影响信号量的状态。
图 2 具有条件变量的管程
现在,假设当操作
x.signal()
被一个进程 P 调用时,在条件变量 x 上有一个挂起进程 Q。显然,如果挂起进程 Q 允许重执行,那么进程 P 必须等待。否则,管程内有两个进程 P 和 Q 可能同时执行。注意,从概念上说两个进程都可以继续执行。有两种可能性存在:
- 唤醒并等待:进程 P 等待直到 Q 离开管程,或者等待另一个条件。
- 唤醒并继续:进程 Q 等待直到 P 离开管程或者等待另一个条件。
对于任一选项,都有赞同理由。一方面,由于 P 已经在管程中执行,唤醒并继续的方法似乎更为合理。另一方面,如果我们允许线程 P 继续,那么 Q 等待的逻辑条件在 Q 重新启动时可能已不再成立。Concurrent Pascal 语言采用这两种选择的折中。当进程 P 执行操作 signal 时,它立即离开管程。因此,进程 Q 立即重新执行。
许多编程语言,如 Java 和 C#,都采用本节所述的管程思想。其他语言,如 Erlang,提供类似机制的并发支持。
所有教程
- socket
- Python基础教程
- C#教程
- MySQL函数
- MySQL
- C语言入门
- C语言专题
- C语言编译器
- C语言编程实例
- GCC编译器
- 数据结构
- C语言项目案例
- C++教程
- OpenCV
- Qt教程
- Unity 3D教程
- UE4
- STL
- Redis
- Android教程
- JavaScript
- PHP
- Mybatis
- Spring Cloud
- Maven
- vi命令
- Spring Boot
- Spring MVC
- Hibernate
- Linux
- Linux命令
- Shell脚本
- Java教程
- 设计模式
- Spring
- Servlet
- Struts2
- Java Swing
- JSP教程
- CSS教程
- TensorFlow
- 区块链
- Go语言教程
- Docker
- 编程笔记
- 资源下载
- 关于我们
- 汇编语言
- 大数据
- 云计算
- VIP视频