0
Can you see the concurrency flaw?
A coworker and I came across this block of code which was causing us numerous headaches over the past few weeks. For a while, there was absolutely no time delay which was causing an inordinate amount of CPU cycles but thats besides the point. After that was fixed with a short delay we were left with what you see below. Can you tell what’s wrong?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | while ( true ) { TriggeredSend ts = queue.peek(); if ( ts != null ) { switch( doPost( ts ) ) { case SUCCESS: queue.take(); ts.complete( true ); break; case FAILURE: queue.take(); ts.complete( false ); break; case SYSTEM_UNAVAILABLE: systemIsAvailable = false; break; } } Thread.sleep( delay ); } |
As with most concurrency bugs, its hard to determine what’s actually happening without experience. You can turn on your debugger but then you are changing the way the code behaves by slowing it down, essentially taking out any race conditions. Turns out, the same task was getting invoked multiple times well as some other strange conditions. That led us to the block of code you see above.
Figure it out yet? Well, what’s happening is that when the code is peeking into the queue, its assigning the result to a variable which is then being called. According to the java.util.concurrency spec, the peek method is used to see if the queue has tasks in it and not used to take any tasks off the queue. Not only that, but after the task was invoked, another task was being pulled off the queue. So what happens when multiple threads come through that block of code and peek? Well, they can both get the same task and invoke it. Bad bad bad.
Categories: Computers, Software