This activity demonstrates the effect of the Java synchronized keyword.
In addition to the Solution document, the project for this activity contains the following classes:
Your task will be to study the classes we have provided, and to alter one of the methods so that the program behaves correctly and the bank account is not left in an inconsistent state.
Here is an explanation of the classes:
BankAccount, which has a single data field balance, and two methods which simply increment the balance by 1, wait a bit, then decrement the balance by 1 again, so that it ends back where it started. This data field is initialised to 0 and so when the method finishes balance will once more be 0, although its value will have been 1 at some point during the execution of the method.
The methods in class BankAccount contain println statements at the appropriate points so that we will know when a method is entered, when it is exited and what the balance is on entry.
One of the methods, methodA, is declared synchronized. The other, methodB, is unsynchronized.
GoodThread. A good thread calls the synchronized methodA. Its run method has a loop which invokes methodA 5 times.
BadThread. A bad thread calls the unsynchronized methodB. Its run method has a loop which invokes methodB 5 times.
Class Main creates a bank account, then creates a good and a bad thread that share the bank account, then starts the two threads.
Build and run the program, setting ex8_4.Main as the main class.
You should see that methodA and methodB can access the shared data concurrently. Evidence for this is that the balance is generally reported as 1. This is because one thread has incremented the balance, but before it can decrement the balance back to 0 and exit the method the other thread has got in and read the incremented value.
What is happening here is that the good thread calls the synchronized methodA and must acquire the lock associated with the BankAccount object in order to execute the method. However this is not enough to protect the data. The bad thread calls the unsynchronised methodB and so does not need to acquire the lock and can go right ahead without it.
Thus nothing stops the bad thread accessing the data before the good thread is finished with it!
Moreover, since the bad thread never acquires the lock, the good thread can always get hold of it, so it can proceed to access the data before the bad thread is through with it.
Now alter methodB so it is synchronized. When you run the program again you should find a dramatic difference. The bad thread must now also acquire the lock belonging to the BankAccount before it can go ahead. Since both threads now require the lock, only one of them can access the data at a time, and once a thread starts executing its method it will finish without interference, and only when it exits will the other thread be able to proceed. You should be able to see this from the printout.
The balance will now always be given as 0, of course, because a thread that gets to increment the balance will also get to decrement it again before the other thread can read its value.