A Simple HVAC System Simulation Part II Jan

  • Slides: 32
Download presentation
A Simple HVAC System Simulation Part II Jan Pettersen Nytun

A Simple HVAC System Simulation Part II Jan Pettersen Nytun

Outline • Towards a more realistic simulation • Single thread • Two threads •

Outline • Towards a more realistic simulation • Single thread • Two threads • Thread. sleep(long millis) • Thread Safe? • Atomic Action • volatile • synchronized 2

Towards A More Realistic Simulation In real life the system can be seen as

Towards A More Realistic Simulation In real life the system can be seen as composted of individually concurrent existing parts that communicate with each other and continuously they change state – it’s like the components have “their own lives”: • The temp. sensor keeps on monitoring the temp. of the room which changes gradually. • The heater keeps on heating the room if it is turned on. • The thermostat gradually regulates the states of the heaters and coolers. Our first goal: Give “life” to the temp. sensor by allocating a separate thread to execute it’s code. A Thread is like an executer – for doing the execution it needs to be allocated a processor and some reference to the code to execute. 3

4

4

New interrupt Ready Event has occurred Terminated Running scheduler selects waiting wait for I/O

New interrupt Ready Event has occurred Terminated Running scheduler selects waiting wait for I/O or some other event 5

= Operating system Scheduler Interrupt-handler = user process Some Hardware Process-1 Process-2 run() schedule()

= Operating system Scheduler Interrupt-handler = user process Some Hardware Process-1 Process-2 run() schedule() ”pause” run() time slice system call 6

7

7

– New/Just Created • Thread is created but not started (Thread. start() has not

– New/Just Created • Thread is created but not started (Thread. start() has not called). – Ready • Thread. start() called and only thread/process scheduling prevents it from being running. – Running • Thread is allocated a processor and is running – Waiting • Waiting for some event to appear, e. g. io-operation to be completed, waiting for access to some resource. – Dead/Terminated • Thread has completed or exited; come to the end of its run() method. • At some point it will be disposed of by run-time system. 8

Old Solution – A Simple HVAC System Simulation Part I The temperature of the

Old Solution – A Simple HVAC System Simulation Part I The temperature of the room is calculated when needed! 9

New Solution First Just One Thread - Overview - • We focus on temp.

New Solution First Just One Thread - Overview - • We focus on temp. sensor and room. • Room. Impl defines a “temp-property”. 10

New Solution First Just One Thread - Code public class Room. Impl implements Room

New Solution First Just One Thread - Code public class Room. Impl implements Room { private double temp; public double get. Temp() { return temp; } public void set. Temp(double temp) { this. temp = temp; } The implementations do not contain much logic at this point! } public class Temp. Sensor. Impl implements Temp. Sensor { private Room room; private double temp; public void set. Room(Room room) { this. room = room; } public double get. Temp() { return temp; } public void run() { temp = room. get. Temp(); } } 11

New Solution First Just One Thread - Code public class Simulation. Monitor. App extends

New Solution First Just One Thread - Code public class Simulation. Monitor. App extends Simulation. Monitor { } public static void main(String[] args) { Simulation. Monitor. App simulation. Monitor. App = new Simulation. Monitor. App(); simulation. Monitor. App. assemble. Objects(); simulation. Monitor. App. run. Simulation(); } Most of the behaviour is defined here! public class Simulation. Monitor { private Air. Temp. Factory. Impl air. Temp. Factory. Impl = new Air. Temp. Factory. Impl(); private Room room = air. Temp. Factory. Impl. create. Room(); private Temp. Sensor temp. Sensor = air. Temp. Factory. Impl. create. Temp. Sensor(); public void assemble. Objects() { System. out. println("Assembling the objects. "); temp. Sensor. set. Room(room); } public void run. Simulation() { System. out. println("n--- Simulation starts ---n"); for (int room. Temp = 0; room. Temp<=20; room. Temp++){ room. set. Temp(room. Temp); System. out. printf("Room temp. set to: %d n", room. Temp); temp. Sensor. run(); double senor. Temp = temp. Sensor. get. Temp(); System. out. printf("Sensor temp. set to: %. 1 f n", senor. Temp); }}} 12

New Solution – One Thread No Surprises! Assembling the objects. --- Simulation starts --Room

New Solution – One Thread No Surprises! Assembling the objects. --- Simulation starts --Room temp. set to: 0 Sensor temp. set to: 0. 0 Room temp. set to: 1 Sensor temp. set to: 1. 0 Room temp. set to: 2 Sensor temp. set to: 2. 0 Room temp. set to: 3 Sensor temp. set to: 3. 0 Room temp. set to: 4 Sensor temp. set to: 4. 0 Room temp. set to: 5 Sensor temp. set to: 5. 0 … Room temp. set to: 18 Sensor temp. set to: 18. 0 Room temp. set to: 19 Sensor temp. set to: 19. 0 Room temp. set to: 20 Sensor temp. set to: 20. 0 13

Introducing An Additional Thread Make Temp. Sensor “runnable” by a separate Thread 14

Introducing An Additional Thread Make Temp. Sensor “runnable” by a separate Thread 14

public class Simulation. Monitor { … public void run. Simulation() { System. out. println("n---

public class Simulation. Monitor { … public void run. Simulation() { System. out. println("n--- Simulation starts ---n"); // Give name to initial thread Thread. current. Thread(). set. Name("Initial thread"); // make a new thread and let it run temp. Sensor Thread sensor. Thread = new Thread(temp. Sensor); sensor. Thread. set. Name("Sensor thread"); sensor. Thread. start(); for (int room. Temp = 0; room. Temp<=20; room. Temp++){ room. set. Temp(room. Temp); System. out. printf(Thread. current. Thread(). get. Name() + ": %d n", room. Temp); } } } public interface Temp. Sensor extends java. lang. Runnable{ public abstract void set. Room(Room room); public abstract double get. Temp(); } public class Temp. Sensor. Impl implements Temp. Sensor { … public void run() { for (int i=0; i<50; i++){ temp = room. get. Temp(); System. out. printf(Thread. current. Thread(). get. Name() + ": %. 1 f n", temp); } } } 15

Introducing An Additional Thread - Output First Run Second Run Assembling the objects. ---

Introducing An Additional Thread - Output First Run Second Run Assembling the objects. --- Simulation starts --- Initial thread: 0 Initial thread: 1 … Initial thread: 20 Sensor thread: 20. 0 … Sensor thread: 20. 0 Initial thread: 1 … Initial thread: 13 Sensor thread: 13. 0 Sensor thread: 14. 0 … Sensor thread: 14. 0 Initial thread: 14 Initial thread: 15 Initial thread: 16 Initial thread: 17 Initial thread: 18 Initial thread: 19 Initial thread: 20 16

One Possible Scenario “ 1: run” is modelled as an asynchronous call. There might

One Possible Scenario “ 1: run” is modelled as an asynchronous call. There might not be true concurrent execution of the two threads, e. g. execution of “ 3: get. Temp” might be temporarily suspended (due to time-sharing) while “ 1. 1: get. Temp” is executed! 17

Introduce Thread. sleep(long millis) public class Simulation. Monitor { … public void run. Simulation()

Introduce Thread. sleep(long millis) public class Simulation. Monitor { … public void run. Simulation() { … for (int room. Temp = 0; room. Temp<=20; room. Temp++){ room. set. Temp(room. Temp); System. out. printf(Thread. current. Thread(). get. Name() + ": %d n", room. Temp); try { Thread. sleep(500); // A half second sleep } catch (Interrupted. Exception e) { e. print. Stack. Trace(); } } public class Temp. Sensor. Impl implements Temp. Sensor { … public void run() { for (int i=0; i<50; i++){ temp = room. get. Temp(); System. out. printf(Thread. current. Thread(). get. Name() + ": %. 1 f n", temp); try { Thread. sleep(500); // A half second sleep } catch (Interrupted. Exception e) { e. print. Stack. Trace(); } } 18

A Run Assembling the objects. --- Simulation starts --Sensor thread: 0. 0 Initial thread:

A Run Assembling the objects. --- Simulation starts --Sensor thread: 0. 0 Initial thread: 1 Sensor thread: 1. 0 Initial thread: 2 Sensor thread: 2. 0 Initial thread: 3 Sensor thread: 3. 0 Initial thread: 4 Initial thread: 5 Sensor thread: 5. 0 Initial thread: 6 Sensor thread: 6. 0 Initial thread: 7 … Sensor thread: 11. 0 Initial thread: 12 Sensor thread: 12. 0 Initial thread: 13 Sensor thread: 13. 0 Initial thread: 14 Sensor thread: 14. 0 Initial thread: 15 Sensor thread: 15. 0 Initial thread: 16 Sensor thread: 16. 0 Initial thread: 17 Sensor thread: 17. 0 Initial thread: 18 Sensor thread: 18. 0 Initial thread: 19 Sensor thread: 19. 0 Initial thread: 20 Sensor thread: 20. 0 19

Is Our Solution Thread Safe? From Wikipedia Thread safety is a computer programming concept

Is Our Solution Thread Safe? From Wikipedia Thread safety is a computer programming concept applicable in the context of multi-threaded programs. A piece of code is thread-safe if it functions correctly during simultaneous execution by multiple threads. In particular, it must satisfy the need for multiple threads to access the same shared data, and the need for a shared piece of data to be accessed by only one thread at any given time. Comment: If there are only simultaneous reads then there is no problem! 20

Atomic Action A sequence of statements, one or more, that appears to be indivisible.

Atomic Action A sequence of statements, one or more, that appears to be indivisible. That is: no other processing activity can see an intermediate state. • Fine-grained atomic action: action – Is implemented as an indivisible machine instruction (e. g. assigning an int in Java). • Coarse-grained atomic action: – A sequence of fine-grained actions that appears to be indivisible by the help of some synchronization mechanism (e. g. database transaction). 21

Atomically Assignable • In Java the primitive types are atomically assignable, except double and

Atomically Assignable • In Java the primitive types are atomically assignable, except double and long. • If you access a double which is concurrently being assigned a value by another thread, the value you get might be different from the old and the new value. This is not the case with an int. 22

From The Java™ Language Specification [1] 23

From The Java™ Language Specification [1] 23

A “Problem Scenario” initial value +1 in two steps 0000… 00000 1111… 11111 0000…

A “Problem Scenario” initial value +1 in two steps 0000… 00000 1111… 11111 0000… 00000 a read at this point in time gives a “dirty read” 0000… 00001 0000… 00000 A potential problem with writing/reading a long 24

Making Sure Reading And Writing Of Temp Is Atomic package airtemp. impl; import airtemp.

Making Sure Reading And Writing Of Temp Is Atomic package airtemp. impl; import airtemp. Room; Fine-grained solution public class Room. Impl implements Room { private volatile double temp; public double get. Temp() { return temp; } public void set. Temp(double temp) { this. temp = temp; } } 25

A More Coarse-Grained Solution It is possible to have mutually exclusive access to temp,

A More Coarse-Grained Solution It is possible to have mutually exclusive access to temp, i. e. let only one thread access temp at a time. The “synchronized” keyword in Java can be used to archive this! 26

Mutual exclusion can be achieved by using method modifier synchronized. public class Box{ private

Mutual exclusion can be achieved by using method modifier synchronized. public class Box{ private Object box. Contents=null; // use put public synchronized Object get(){ Object contents = box. Contents; box. Contents = null; return contents; } For an object of type Box only one thread can at the same time execute put or get. public synchronized boolean put( Object contents){ if (box. Contents != null) return false; box. Contents = contents; return true; } Eg. if one thread is executing put and another thread calls get; the thread trying to execute get must wait until the } first one is finished executing put. 27

Establishing Exclusive Access To temp By Synchronizing The methods package airtemp; public interface Room

Establishing Exclusive Access To temp By Synchronizing The methods package airtemp; public interface Room { public abstract double get. Temp(); public abstract void set. Temp(double temp); } A more coarsegrained solution public class Room. Impl implements Room { private double temp; public synchronized double get. Temp() { return temp; } public synchronized void set. Temp(double temp) { this. temp = temp; } } 28

A Run Assembling the objects. --- Simulation starts --Initial thread: 0. 0 Sensor thread:

A Run Assembling the objects. --- Simulation starts --Initial thread: 0. 0 Sensor thread: 0. 0 Initial thread: 1. 0 Initial thread: 2. 0 Initial thread: 3. 0 Initial thread: 4. 0 Initial thread: 5. 0 Initial thread: 6. 0 Initial thread: 7. 0 Initial thread: 8. 0 Sensor thread: 1. 0 Sensor thread: 8. 0 Sensor thread: 9. 0 … … Sensor thread: 9. 0 Initial thread: 9. 0 Sensor thread: 10. 0 Initial thread: 11. 0 Initial thread: 12. 0 Initial thread: 13. 0 Initial thread: 14. 0 Initial thread: 15. 0 Initial thread: 16. 0 Initial thread: 17. 0 Initial thread: 18. 0 Initial thread: 19. 0 29

Minimizing the time a thread keeps a lock is a good thing: waiting is

Minimizing the time a thread keeps a lock is a good thing: waiting is reduced since the object is locked for a shorter time (the chance of finding the object unlocked is bigger) and the chance for deadlock is also reduced (less statements in a critical region reduces the public class Account{ change of deadlock). private float balance = 0 ; Instead of synchronizing a complete method it is possible to synchronize a block. public void transaction(float amount){ synchronized(this){ balance = balance + amount; }; } } 30

Establishing Exclusive Access To temp By Synchronizing “Method-Body-Code” public class Room. Impl implements Room

Establishing Exclusive Access To temp By Synchronizing “Method-Body-Code” public class Room. Impl implements Room { private double temp; public double get. Temp() { double local. Temp; synchronized (this){ local. Temp = temp; } return local. Temp; } In our case it is not so easy to see if this solution is more fined grained then using synchronized on the method! At this point it seems that using volatile is best and sufficient! public synchronized void set. Temp(double temp) { synchronized (this){ this. temp = temp; } } } 31

References • [1] The Java™ Language Specification, James Gosling, Bill Joy, Guy Steele, Gilad

References • [1] The Java™ Language Specification, James Gosling, Bill Joy, Guy Steele, Gilad Bracha 32