This interleaving of events can't happen, because entries.put() implicitly synchronizes on the entries SynchronizedMap.

I think I found the problem, though: in allocate(), you moved the processing of the found entry outside of the loop. But the `free` variable is always initialized with the last entry in the free list, regardless of whether it is locked or not, if there is at least one free entry bigger than the one we're looking for.