aspose file tools*
The moose likes Threads and Synchronization and the fly likes blocking call to release() Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "blocking call to release()" Watch "blocking call to release()" New topic
Author

blocking call to release()

Jean-Michel Vilain
Greenhorn

Joined: Aug 06, 2010
Posts: 17

Hi there

I have wasted a huge amount of time trying to understand a specific issue in my code, it happens very rarely and when it happens my main scheduler gets blocked.
I have added logs and found out that the instruction never ends:


I have a hard time believing that, how can a release be blocked? It's the purpose and nature of a acquire(), but a release, I don't get it.
Clues most welcome, thanks!


Designer and developer on Faëria: Strategy Card Game (www.faeria.net). The server is 100% Java.
@Jiem_ on Twitter (http://twitter.com/Jiem_)
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1011
    
  15
Even I am going through Thread Schedulers again to see if I can get a clue. Cause as far as I remember and as far as( I think so) Semaphore logic is concerned, since Semaphores follow a non ownership of permits, and it's the acquires that block, a release should not block. In fact we can issue a release even though the number of permits available is equal to the number of maximum permits in which case the release causes the number of max permits to increase by one. Unlike locks we don't even get an exception if a thread that is not holding a permit issues a release.

By the way, have you checked it well that it is the release that is blocking? Even the API does not say that a release can block. I mean have you reviewed your logger's logic?
But I'm not sure if this could be dependent on how you are using the Semaphores or if it is related to Schedulers. I'm studying Schedulers again to revise and to get a hint.

I'm also curious as to what the experts are gonna say on this one.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4176
    
  21

Is that a java.util.concurrent.Semaphore?

If so, I don't think it is impossible to get a blocking behavior in the release() method, but it is unlikely. The release is done 'optimistically' which means it doesn't use synchronization (block others from entering blocks of code: pessimistically: assumes lots of contention) it instead assumes there won't be much contention. It sets a value then checks to see if the value successfully set. If it was not successful (because another thread also set the same value) then try again. This is done in an infinite loop - the assumption being that it will eventually finish and the few times where there is contention and you have to run the loop many times is going to have less of an effect on timing than always excluding threads from executing blocks in parallel.

So the possible blocking scenario is if multiple threads are trying to set the same semaphore's value differently. Each one interferes with the other and a sort of periodicity happens where enough interaction happens that hangs threads indeterminately as they all try and fail to successfully change the value. For this to be the case, you will need multiple threads, and probably many of them, all working on the same Semaphore. And I believe they all should end up appearing to block (though if you used a monitor they shouldn't go into a blocked or waiting state). If this is happening then it means that you have more contention for the value than you thought - perhaps you should consider a different mechanism that is more pessimistic.

Steve
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18717
    
  40

Steve Luke wrote:Is that a java.util.concurrent.Semaphore?

If so, I don't think it is impossible to get a blocking behavior in the release() method, but it is unlikely. The release is done 'optimistically' which means it doesn't use synchronization (block others from entering blocks of code: pessimistically: assumes lots of contention) it instead assumes there won't be much contention. It sets a value then checks to see if the value successfully set. If it was not successful (because another thread also set the same value) then try again. This is done in an infinite loop - the assumption being that it will eventually finish and the few times where there is contention and you have to run the loop many times is going to have less of an effect on timing than always excluding threads from executing blocks in parallel.

So the possible blocking scenario is if multiple threads are trying to set the same semaphore's value differently. Each one interferes with the other and a sort of periodicity happens where enough interaction happens that hangs threads indeterminately as they all try and fail to successfully change the value. For this to be the case, you will need multiple threads, and probably many of them, all working on the same Semaphore. And I believe they all should end up appearing to block (though if you used a monitor they shouldn't go into a blocked or waiting state). If this is happening then it means that you have more contention for the value than you thought - perhaps you should consider a different mechanism that is more pessimistic.



A little bit more details about optimistic algorithms -- In general, they get the parameters, work on it in isolation, and when conditionally store the result. The result is stored, if and only if, the parameters has not changed. This checking and storing of the result is done atomically -- meaning it is not possible for the parameters to change from the check to the storing of the result. In the case of the semaphore, lets assume that the parameter is the number of permits, the work is incrementing the number of permits, and the final part is storing the new number of permits, if and only if, the number of permits has not changed since we last read it.

Interestingly, when a collision occurs, one thread gets through -- the first one that changed the variable. This means that it is not possible for two threads to perpetually collide with each other (for performing one optimistic operation each), one thread should get through each time. This means, that for a thread to be constantly colliding (endlessly), there needs to be an endless number of operations colliding with it -- and these operations need to win every time...

I know that Steve stated that it is very unlikely (to the point of impossible), I will go one step further, and state that unless there is an endless number of acquires and releases happening, which can in theory collide with this release operation, it *is* impossible that the release is blocked forever.

Henry

Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4176
    
  21

Thanks Henry, the part that made me feel it wasn't impossible was that I had the check and set in reverse order - my poor reading of the mechanism. Thanks for clearing it up.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18717
    
  40

Jean-Michel Vilain wrote:
I have wasted a huge amount of time trying to understand a specific issue in my code, it happens very rarely and when it happens my main scheduler gets blocked.
I have added logs and found out that the instruction never ends:


I have a hard time believing that, how can a release be blocked? It's the purpose and nature of a acquire(), but a release, I don't get it.
Clues most welcome, thanks!



BTW, the last time someone claimed that a method call, that should never block, does indeed block -- and proved it by a logger -- I proved that it was faulty logging.

In that case, I wrapped the operation in a try-finally block, and had logging report the exit from the method in the finally block. The issue was that an exception was thrown, so the exit log message was never seen (until I placed it in a finally block).

Henry
Jean-Michel Vilain
Greenhorn

Joined: Aug 06, 2010
Posts: 17

Guys, my dearest apologies.
I didn't realize... this instruction is at the beginning of a synchronized function.
°_+
Well, at least I have encountered my very first deadlock!
I will confirm ASAP and tell you more about this specific case, deadlocks are rare. Meanwhile I thank you all.

Btw, yes I have recently noticed that the finaly clause is clearly underrated =]
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1011
    
  15
Thanks Steve, and Henry. Such posts are giveaways. We get to know about the implementation level details without having to go through the src ( whenever I've gone through few programs in the src folder, the process has been time consuming. Many times I actually gave up on it. ) folder.

And I had not even heard of classifying algorithms this way - optimistic and pessimistic algorithms for synchronization. Such an interesting thing really. And we can apply this to most ( perhaps - cause 'all' is too strong a word ) algorithms and it is nice cause optimistic algorithms would in general follow similar approach to achieving controlled ( liberally/least controlled ) concurrency, and pessimistic algorithms would enforce some sort of an exclusive locking variant.

Thanks so much.
Chan.
Jean-Michel Vilain
Greenhorn

Joined: Aug 06, 2010
Posts: 17

Indeeed, incredibly instructive read.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: blocking call to release()