Concurrent Programming with Java
Lab Manual, Version 1.0, F. Astha Ekadiyanto,
2002.
In a multithreading environment, whenever there are two or more threads sharing access to a common object or memory, a race condition may occur. This is due to the way threads work (either concurrent or parallel) that may result in an inconsistent state. We will try a simple code to demonstrate this behaviour and try to overcome the problem.
The common Object that will be shared is the Briefkasten Class. The Class definition is very straight forward. It has a private field content, a get() method to get the content and a put() method to change the content.Create this class in your new BlueJ Project.
Then we will define two types of threads to share the Briefkasten, namely the Mieter Class that will access the get() method and the Postbote Class that will access the put() method.
The Mieter Class is as follows:
The Postbote Class is as follows:
Now let us make a small application to test our codes. Create a RaceCondition Class as follows:
public class RaceCondition { public static void main(String[] args) { Briefkasten b = new Briefkasten(); Mieter m1 = new Mieter(b, 1); Postbote b1 = new Postbote(b, 1); b1.start(); m1.start(); } } |
Then run the application and observe the results. It will be more or less behaves like the followings:
We could run the main() method for a couple of times and results in different behavior but with similar symptom. The Postbote and the Mieter is racing to access the Briefkasten.
The problem with the codes is the state of the Briefkasten should be checked before changing the content. Let us try to address the problem by modifying the Briefkasten Class:
Then run the application and observe the results. It will be more or less behaves like the followings:
Postbote #1 put: 1 Mieter #1 got: 1 Postbote #1 put: 2 Mieter #1 got: 2 Postbote #1 put: 3 Mieter #1 got: 3 Postbote #1 put: 4 Mieter #1 got: 4 Postbote #1 put: 5 Mieter #1 got: 5 Postbote #1 put: 6 Mieter #1 got: 6 Postbote #1 put: 7 Mieter #1 got: 7 Postbote #1 put: 8 Mieter #1 got: 8 Postbote #1 put: 9 Mieter #1 got: 9 Postbote #1 put: 10 Mieter #1 got: 10 |
Great! Now it works fine. The Mieter will only get some thing if it finds the Briefkasten is filled and the Postbote will put something only when it finds the Briefkasten is not filled otherwise, they will wait().
But! The code may have additional problem. The following modification in the RaceCondition Class will demonstrate the problem.
Instead of only single Mieter, now we will have two Mieters to access the same
Briefkasten.
Run the application and observe the results. It will be more or less behaves
like the followings:
Postbote #1 put: 1 Mieter #1 got: 1 Postbote #1 put: 2 Mieter #2 got: 2 Mieter #1 got: 0 Postbote #1 put: 3 Mieter #2 got: 3 Postbote #1 put: 4 Mieter #1 got: 4 Postbote #1 put: 5 Mieter #2 got: 5 Postbote #1 put: 6 Mieter #1 got: 6 Postbote #1 put: 7 Mieter #2 got: 7 Postbote #1 put: 8 Mieter #2 got: 8 Postbote #1 put: 9 Mieter #1 got: 9 Mieter #2 got: 0 Postbote #1 put: 10 Mieter #1 got: 10 |
It seems like some Mieter still trying to access the Briefkasten when it is actually empty (indicated by 0 value). Could you solve the mystery?