views:

414

answers:

1

In one of my recent answers, I gave a theoretical semaphore example of limiting access to memory resources:

public static byte[] createArray(int size) throws InterruptedException {
    semaphore.acquire(size);
    return new byte[size];
}
public static void releaseArray(byte[] array) {
    semaphore.release(array.length);
}

I think this can be a source of deadlock if the allocation interleaving is bad:

semaphore = new Sempaphore(30, true);
// T1                                 T2
//--------------------------          ----------------------
a1 = createArray(10);                                           // 20
                                      a3 = createArray(10);     // 10
a2 = createArray(15);                                           // wait
                                      a4 = createArray(15);     // wait
// ...                                // ...
releaseArray(a1);                     releaseArray(a3);
releaseArray(a2);                     releaseArray(a4);

Is my observation true? If yes, how can I avoid this situation (e.g timed wait and rollback)?

+2  A: 

Yes, using Semaphore.tryAcquire(permits, timeout, timeUnit) would be the sensible thing to do here. Obviously you've got to be careful to release the semaphore in a finally block to avoid leaks...

Jon Skeet
Thanks. I was more interested in how to the rollback in case of the exception - in the sample case it's easy, just release and return to line 1 and retry. But I fear when the in-thread allocation is more further away (enclosing an expensive computation for example), that can't help either. Maybe I should revert back to a more coarse grained locking schema?
kd304
You'd have to give details of the more complex example to say for sure - but I guess one approach is to roll back all *related* resources and retry... perhaps rolling back further and further each time, to allow other tasks more chance to complete.
Jon Skeet