Reputation: 1495
I need a semaphore with the following features:
I have written the following code:
public class SimpleSemaphore
{
private int permits;
private AtomicLong counter = new AtomicLong();
SimpleSemaphore(int permits)
{
this.permits = permits;
}
boolean acquire()
{
if (counter.incrementAndGet() < permits)
{
return true;
}
else
{
counter.decrementAndGet();
return false;
}
}
void release()
{
counter.decrementAndGet();
}
}
Another option is this Semaphore:
public class EasySemaphore
{
private int permits;
private AtomicLong counter = new AtomicLong();
EasySemaphore(int permits)
{
this.permits = permits;
}
boolean acquire()
{
long index = counter.get();
if (index < permits)
{
if (counter.compareAndSet(index, index + 1))
{
return true;
}
}
return false;
}
void release()
{
counter.decrementAndGet();
}
}
Are the both implementations thread-safe and correct? Which one is better? How would you go about this task?
Upvotes: 2
Views: 2679
Reputation: 262852
Doesn't java.util.concurrent.Semaphore
already do all that?
It has a tryAcquire
for non-blocking acquire, and it maintains a simple count of remaining permits (of which the same thread could take out more than one).
Upvotes: 7
Reputation: 533880
I would say the second one is better as the counter will never be greater thathan 0 (and its slightly more efficient)
I would use a loop otherwise you can have the method fail when there is still permits left.
public class EasySemaphore {
private final AtomicInteger counter;
EasySemaphore(int permits) {
counter = new AtomicInteger(permits);
}
boolean acquire() {
// highly unlikely to loop more than once.
while(true) {
int count = counter.get();
if (count <= 0) return false;
if (counter.compareAndSet(count, count -1))
return true;
}
}
void release() {
counter.incrementAndGet();
}
}
Upvotes: 0