You should not need any logical locking - certainly not for this scenario.
It is not possible for two threads to "keep noticing" that one slot is still free. The only way for one thread to get rolled back is if another thread has successfully committed - meaning that the last slot has been filled.
Deadlock is guaranteed to never happen because locking happens only during the commit phase, and by then we know exactly what to lock, and can take locks in a consistent order. Livelock is guaranteed to never happen because one transaction can only ever rolled back because another transaction committed successfully. It is therefore impossible for two transactions to block each other forever.
What is theoretically possible is starvation. One particularly unlucky transaction could be rolled back infinity times. This can only happen if an infinite number of conflicting transactions are committing successfully. So globally, the system must make progress, but locally, one specific transaction can get stuck.
In practice, the only way this is likely to happen is if you're running an infinite stream of short transactions, and then you start one very long transaction which thus never gets to complete.