Skip to content

#466: Monitor object #768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions monitor-object/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
layout: pattern
title: Monitor Object
folder: monitor-object
permalink: /patterns/monitor-object/
categories: Concurrency
tags:
- Java
- Difficulty-Intermediate
---

## Intent
In 1974, Tony Hoare proposed the concept of monitors for designing and reasoning about objects that are shared between multiple threads. The key property of these "Hoare-style" monitors is that threads can wait until some specific assertion about the monitor's state is true and be guaranteed that it is still true after the thread has been awakened. The purpose of the Monitor Object is to provide an implementation of Hoare-style monitors for thread communication in a Java-based monitor package that automates assertion checking during execution. This approach reduces redundant coding and automates assertions checking during execution.

![alt text](./etc/monitor-object.png "Monitor Object Pattern")

## Applicability
Use the Monitor Object Pattern for thread signaling (over Java's wait() and notify() approach) in the following situations:

* When you need Defensive programming in multithreaded code - The monitor package provides support for defensive programming through the invariant() method and the assertion objects associated with each condition object. Java's notify() and wait() provide no assertion checking
* When you need objects to wait on multiple wait queues - The monitor package provides condition objects, each providing its own wait queue. Threads waiting for different assertions to become true wait on different queues. Using wait(), there is only one wait queue per object.
* When you need seamless passing of occupancy - In the monitor package, control is passed seamlessly from the signaling thread to an awaiting thread. You can be sure that, after returning from an await(), the assertion the thread has waited for is true. In contrast, the notify() and notifyAll() methods simply move a waiting thread back to the entry queue for the monitor.

## Credits

* [Theodore S. Norvell - Monitor Object](https://www.javaworld.com/article/2077769/core-java/better-monitors-for-java.html)
* [Monitor (syncronization)](https://en.wikipedia.org/wiki/Monitor_(synchronization))
Binary file added monitor-object/etc/monitor-object.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
158 changes: 158 additions & 0 deletions monitor-object/etc/monitor-object.ucls
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.2.2" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
realizations="true" associations="true" dependencies="false" nesting-relationships="true" router="FAN">
<class id="1" language="java" name="com.iluwatar.monitor.AbstractMonitor" project="monitor-object"
file="/monitor-object/src/main/java/com/iluwatar/monitor/AbstractMonitor.java" binary="false" corner="BOTTOM_RIGHT">
<position height="567" width="287" x="20" y="-114"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="2" language="java" name="com.iluwatar.monitor.Condition" project="monitor-object"
file="/monitor-object/src/main/java/com/iluwatar/monitor/Condition.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="839" y="263"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="3" language="java" name="com.iluwatar.monitor.Assertion" project="monitor-object"
file="/monitor-object/src/main/java/com/iluwatar/monitor/Assertion.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="824" y="669"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="4" language="java" name="com.iluwatar.monitor.Monitor" project="monitor-object"
file="/monitor-object/src/main/java/com/iluwatar/monitor/Monitor.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="155" y="668"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="5" language="java" name="com.iluwatar.monitor.MonitorListener" project="monitor-object"
file="/monitor-object/src/main/java/com/iluwatar/monitor/MonitorListener.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="674" y="-108"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<class id="6" language="java" name="com.iluwatar.monitor.Semaphore" project="monitor-object"
file="/monitor-object/src/main/java/com/iluwatar/monitor/Semaphore.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="488" y="350"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="7" language="java" name="com.iluwatar.monitor.Semaphore.QueueElement" project="monitor-object"
file="/monitor-object/src/main/java/com/iluwatar/monitor/Semaphore.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="488" y="571"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="8" language="java" name="com.iluwatar.monitor.TrueAssertion" project="monitor-object"
file="/monitor-object/src/main/java/com/iluwatar/monitor/TrueAssertion.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="1063" y="670"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<association id="9">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="10" name="invariant"/>
<multiplicity id="11" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="3" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="12">
<end type="SOURCE" refId="2" navigable="false">
<attribute id="13" name="homeMonitor"/>
<multiplicity id="14" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="1" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="15">
<end type="SOURCE" refId="8" navigable="false">
<attribute id="16" name="SINGLETON"/>
<multiplicity id="17" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="8" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="18">
<end type="SOURCE" refId="1" navigable="false">
<attribute id="19" name="entrance"/>
<multiplicity id="20" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="6" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<generalization id="21">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="1"/>
</generalization>
<nesting id="22">
<end type="SOURCE" refId="6"/>
<end type="TARGET" refId="7"/>
</nesting>
<association id="23">
<end type="SOURCE" refId="6" navigable="false">
<attribute id="24" name="queue"/>
<multiplicity id="25" minimum="0" maximum="2147483647"/>
</end>
<end type="TARGET" refId="7" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="26">
<end type="SOURCE" refId="2" navigable="false">
<attribute id="27" name="queue"/>
<multiplicity id="28" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="6" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<generalization id="29">
<end type="SOURCE" refId="8"/>
<end type="TARGET" refId="3"/>
</generalization>
<association id="30">
<end type="SOURCE" refId="2" navigable="false">
<attribute id="31" name="assertion"/>
<multiplicity id="32" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="3" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="33">
<end type="SOURCE" refId="1" navigable="false">
<attribute id="34" name="listOfListeners"/>
<multiplicity id="35" minimum="0" maximum="2147483647"/>
</end>
<end type="TARGET" refId="5" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</classifier-display>
<association-display labels="true" multiplicity="true"/>
</class-diagram>
48 changes: 48 additions & 0 deletions monitor-object/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0"?>
<!--

The MIT License
Copyright (c) 2014 Ilkka Seppälä

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

-->
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<artifactId>monitor-object</artifactId>
<name>monitor-object</name>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Loading