Maybe I must move away from the pc for a while :-)
I call my "unlock()" method from a "finally" block. The unlock() method, is a standard method with a synchronized block where I synchronize on my map where I keep the record numbers with cookie values. Now, I startup my test app (creating 5 threads) which locks a record, read the record and then in a finally block unlocks the record.
My problem is that when I specify a record to unlock that is not in the cookie-map, it then throws an exception but then the app hangs. I've tried a load of different things - from inserting wait() and notifyAll() in a few different places, but no-go.
How can you unlock a record that is not in the cookie map? You lock the record, you read the record and you unlock the record. And i guess it is just for testing purposes, because you don't need to lock/unlock the record just for reading.
I guess your app hangs because not each thread is getting notified, because the exception is thrown. I would expect your unlock method looks like this:
So you are testing a situation that should never occur in real life when you developed your application well! Because you have to develop your application in such a way that you can't unlock a record that isn't locked.
If you have a scenario where 2 threads are already finished, 2 other threads lock record 1, then 1 thread will be waiting for the lock on record 1 to be released. If then thread5 unlocks record -10 (a non-existing record that is), then the waiting thread will never be notified and your application hangs.
I'm having a similar problem with it hanging but when I actually have a record in the map. I created a simulation where one thread obtains the lock on record 1 and another thread attempts to obtain a lock on the same record, the output is below:
thread 8 attempting to obtain lock on record 1
recordNo 1 locked? false
thread 10 attempting to obtain lock on record 1
recordNo 1 locked? true
currentThread ID=8 returning lock
The code in my unlock method looks something like this:
I'm definitely doing something wrong because my notifyAll() doesn't seem to have an effect. Am I synchronizing on the incorrect object?
When you mark all your public methods synchronized (the simplest approach, the one I followed) you are synchronizing on the this-object. When you want to use synchronized blocks, you can synchronize on the this-object or you can synchronize on another object. One important note is that the 2 threads should access the same object (so the same instance). That's one of the basics of synchronizing and thread interaction, you should be familiar with it, because you had to learn the basics for the scjp exam.
That's why marking all public methods of the Data class synchronized will work only if combined with the singleton design pattern.
Let's assume you have following code:
a snippet from the lock-method:
a snippet from the unlock-method:
This code is just to explain how locking is supposed to be implemented when using wait/notify/notifyAll-mechanism. So you must have 1 object that will be accessed by many threads.
If you call wait on objectA, you have to call notify or notifyAll on objectA too. You clearly struggle with the concepts and understanding of locking and thread interaction. So i would advise you to do some extra studying on this part: have another read of the K&B-book (if you still have it) or the SCJD-book (by Andrew Monkhouse), because this part is the biggest challenge of this assignment. If you don't have locking spot on, you risk a failure.
Roel, don't worry, in fact I do not lock and unlock when reading a record, I'm purely just testing the app to see what happens IF something goes wrong. It definitely should not hang though, but after all the replies now, I'll quickly see if I can see where my issue is.