I created my own simple, compact ReadWriteLock implementation. The first one uses spinlocks upon trying to acquire a read lock. If the lock bit is set, the second avoids spinlocks by momentarily acquiring the write lock before spinning. That way, it halts its execution until the write lock have been freed. Now my question is which is more efficient and optimized for common use? (both multi-core and non-multi-core machines)
Edit: It is going to be used for my Android app. So I have to keep it compact while providing the ReadWriteLock implementation I need. ReentrantReadWriteLock is heavy for my app. Also, can anyone suggest a better method?
Edit: The implementation details were taken from this link.
The first implementation is as follows:
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
public class SpinSeqLock {
private AtomicLong status = new AtomicLong();
private ReentrantLock writeLock = new ReentrantLock();
public long readLock() {
long current;
do
current = status.get();
while ((current & 1) != 0);
return current;
}
public boolean tryReadUnlock(long previous) {
return status.get() == previous;
}
public void writeLock() {
writeLock.lock();
status.incrementAndGet();
}
public void writeUnlock() {
status.incrementAndGet();
writeLock.unlock();
}
public void writeLockInterruptibly() throws InterruptedException {
writeLock.lockInterruptibly(); // If we get interrupted, do not proceed below!
// Increment only on successful uninterrupted lock
status.incrementAndGet();
}
}
The second implementation is as follows:
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
public class SemiSeqLock {
private AtomicLong status = new AtomicLong();
private ReentrantLock writeLock = new ReentrantLock();
public long readLock() {
for (;;) {
long current = status.get();
if ((current & 1) == 0)
return current;
writeLock.lock(); // Avoids spin lock by halting until lock-acquisition.
writeLock.unlock();
}
}
... // Same code as the first one
}
The expected usage would be:
Reader Thread:
for (;;) {
final long status = seqLock.readLock();
// ... some read operation ...
// ... some read operation ...
if (seqLock.tryReadUnlock(status)) break;
}
Writer Thread:
seqLock.writeLock();
try {
// ... some write operation ...
// ... some write operation ...
} finally {
seqLock.writeUnlock();
}
Any corrections? Which one is better?