Sometime, I find in some Java code, they use nested lock to accomplish the syncronization method. code as below
// lock for appending state management
final Lock appendLock = new ReentrantLock();
// global lock for array read and write management
final ReadWriteLock arrayReadWritelock = new ReentrantReadWriteLock();
final Lock arrayReadLock = arrayReadWritelock.readLock();
final Lock arrayWriteLock = arrayReadWritelock.writeLock();
private MapEntry acquireNew(int length) throws IOException {
MapEntry mapEntry = null;
try {
arrayReadLock.lock(); //THE FIRST LOCK
IMappedPage toAppendIndexPage = null;
long toAppendIndexPageIndex = -1L;
long toAppendDataPageIndex = -1L;
long toAppendArrayIndex = -1L;
try {
appendLock.lock(); //THE SECOND LOCK
if (this.isFull()) {
throw new IOException("ring space of java long type used up, the end of the world!!!");
}
if (this.headDataItemOffset + length > DATA_PAGE_SIZE) {
if (this.headDataPageIndex == Long.MAX_VALUE) {
this.headDataPageIndex = 0L;
} else {
this.headDataPageIndex++;
}
this.headDataItemOffset = 0;
}
toAppendDataPageIndex = this.headDataPageIndex;
..........
..........
mapEntry = new MapEntry(toAppendArrayIndex, length, toAppendIndexItemOffset, toAppendIndexPage, this.dataPageFactory);
mapEntry.MarkAllocated();
this.totalEntryCount.incrementAndGet();
this.totalSlotSize.addAndGet(length);
this.arrayHeadIndex.incrementAndGet();
IMappedPage metaDataPage = this.metaPageFactory.acquirePage(META_DATA_PAGE_INDEX);
ByteBuffer metaDataBuf = metaDataPage.getLocal(0);
metaDataPage.setDirty(true);
} finally {
appendLock.unlock();
}
} finally {
arrayReadLock.unlock();
}
return mapEntry;
}
This puzzles me because the first lock has been used, why the author use another lock again?