Roel De Nijs wrote:how would you handle an InterruptedException (if you call object.wait() you have to catch such an exception)?
1. do you just log it ?
2. do you rethrow it in a RuntimeException ?
3. defer it with Thread.currentThread().interrupt(); ? (like said in this article)
I'm for the third variant. I do not allow a thread which is waiting to lock a record to be interrupted
because my specifications are saying that a record should be unlocked only as a result of an unlock.
(or at least I interpreted so )
So, I try my Condition.await() in a loop, if InterruptedException is detected I set a flag and when I'm
done with the method, in finally I call (if i detected an interruption while waiting)
. Like in the article.
I guess you meant the book "Java Concurrency in Practice" by Brian Goetz. I don't have that book, but the article i mentioned is from the same author so both will have same content and same conclusion. I will use the 3rd variant
But, what are the consequences? What does that mean "reinterrupt"? What does that mean for current thread and what does that mean for our code higher upon the call stack (especially in networking mode with RMI)? i wasn't able to make head of that article posted above...
About the InterruptedException.. using the 3rd variant is the correct approach. The interrupt() method simply sets the interrupt flag of that thread to true so if you have a while loop like this:
When 2 threads try to execute the above code, one of them will wait. Now the 1st thread "cancel" the request, then this thread will "interrupt" setting that thread's interrupt flag to true. Now what will happen if the while condition is true... it will "always" throw InterruptedException because the interrupt flag is already set true. Like an infinite loop even it shouldn't be.
Hmm I hope I'm not giving out something else. Anyway re-interrupt in this particular case is setting a flag to tell the JVM or program something went wrong. Ultimately, depending on how you call or access such code, it usually goes up the call stack informing (eg Swing in SCJD) to prompt an error or something.
Hmmmm, that leads me to another point: let's assume thread-1 is the winner of getting access to your code shown above.
What happens to thread-2 when some Exception occurs in that code block while thread-1 has the lock? thread-2 that is still waiting (for some notify/notifyAll-call).
Am i right? Pretty unsure now...
Hmm good point. What would happen to thread2? Ok think about it, if thread1 got interrupted, would thread1 "release" the lock so that thread2 can access the lock? If so, hurray... if not poor you deadlock (must avoid!!)
ok, i know about this issue, but....thread-2 is still waiting....please let's take a look at my locking method and assume that
DatabaseFileAccess.checkRecordNoValid(recNo) throws some "RecordNotValidException".
thread-1 finally unlocks, but thread-2 is still in wait-state and needs some notify-call, right? totally confused now....
I checked my code again to be really sure and I implemented the code from "Noncancelable task that restores interrupted status before returning" (from the article I mentioned). And I explained my decision in choices.txt because a thread should only be woken up by a call of unlock-method, so interruption is not a call to unlock-method (according to the comments of the lock-method of the provided interface).
i agree with you totally. But what should happen in case of an InterruptedException that leads threads to wait infinitely. Some similar situation would be the following.
Two Threads, both want to lock some items (perhaps subcontractors ). Both call lock()-method like shown in that part of code:
If that code snippet is called by thread-1, he exits after putting that item into the map, then calls lock.unlock() in finally-block and then ends up throwing exception (e.g. show exception to user). thread-1 now cannot unlock it because it ends up with exception. Now thread-2 can enter that locking code but has to wait (because item IS in map). What to do now??? i really don't know how to handle these situations? Do you?
If I understand you correctly you are wondering about what to do when a thread has successfully locked record 1, but due to some reason it can't unlock the record (an exception being thrown for example) and that will cause another thread (which waits for the lock on record 1 to be released) to wait forever. Is my understanding correct?
That's something you should solve in the code that's calling the methods from Data class. For example (pseudo-code style):
The call to the unlock method will always be executed, so if an exception occurs, the record will still be unlocked (and the other thread won't have to wait forever).
Another scenario could be (if you are using a thick/fat client approach) a client that crashes after locking the record. How you can possibly handle that one, you can read here.
And as a final remark I want to say that you have to try to keep the time a record is locked as short as possible.
it's me again related to that topic. I'm currently re-validating my design choices and that brings me back to how to deal with InterruptedException within my thick-client... (ohhhh, i would be glad if i would have chosen a thin one.... )
Ok, let's assume the following locking method:
...and handling InterruptedException with a re-interrupt through Thread.currentThread().interrupt().
Now, my client looks like the following (close to that Roel wrote):In my case no Exception is thrown, just re-interupted. After executing the lock()-method, the client code goes on an thinks everything went fine on lock() call. The client assumes that he got the lock and goes on with update()-method. My problem is, that i have no choice to handle that interrupted status i have set it to true calling interrupt(). (That's one of the reasons i wished i had chosen a thin-client). the only possibility would be to handle it within my facade, my layer between data class and client, but what to do with that information (isInterrupted() == true)? Roel, you mentioned you implemented a "Noncancelable task that restores interrupted status before returning" from that article you posted. Surely you will react on that Interruption in a way not to proceed in lock()-method on server-side right? And what sees the client in such a case?
What to do now since the signature of the lock()-method shown to the client is the following?
Perhaps it's better to throw an exception? What do you think?
To be honest, this was the last thing I handled when doing my assignment and I was really happy the end was near, so wanted to finish the assignment as soon as possible
Surely you will react on that Interruption in a way not to proceed in lock()-method on server-side right? And what sees the client in such a case?
Yes, that's the exact reason I used in my choices.txt (a thread will keep waiting until it is cleanly woken up, by the call to notifyAll in the method unlock). And what the client sees in such a case I don't know
I know my good buddy Roberto Perillo (still waiting for invitation to sunny Brazil ) also used a thick client and I believe he wrapped the InterruptedException in a RuntimeException (but I could be wrong here and then he certainly will correct me). I stuck also for a long time to throwing an Exception, but changed in the end to the "restoring interruption status" (as a result of Liviu's comment). I think that every approach will be considered ok as long as you not simply ignore it or just log it.
Roel De Nijs wrote:I know my good buddy Roberto Perillo (still waiting for invitation to sunny Brazil ) also used a thick client and I believe he wrapped the InterruptedException in a RuntimeException (but I could be wrong here and then he certainly will correct me).
Ok, first let me explain: this is something that I remember I was going to search for a good solution, but I forgot to change before submitting the project. Here's what I ended up delivering:
Shame on me! This is like swallowing the exception! Yeah, I know... I was going to change this for wrapping this exception into a RuntimeException. Another valid approach is to include the InterruptedException in the throws clause of the method (when possible). In our case, the lock method does not declare its throws clause, so in my opinion, it is the best approach to be taken.
PS: Roel, you are welcome here any time you want to come over! Just tell me when you want to come to Brazil, and I'll organize some trips to some cool beaches, and we can also play some soccer there, man!!!
shame on you!!! Swallowing InterruptedException...
Well, after thinking about that issue, i think i will throw a RuntimeException. Indeed, that's what i wanted to avoid, but following my architecture that will be the most intelligent approach.