Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does StampedLock.writeLock() release a read-lock held by the current thread?

http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/ contains this code:

StampedLock lock = new StampedLock();
long stamp = lock.readLock();
try {
  if (count == 0) {
    stamp = lock.tryConvertToWriteLock(stamp);
    if (stamp == 0L) {
      System.out.println("Could not convert to write lock");
      stamp = lock.writeLock();
    }
    count = 23;
  }
  System.out.println(count);
} finally {
  lock.unlock(stamp);
}

The author writes:

Calling tryConvertToWriteLock() doesn't block but may return a zero stamp indicating that no write lock is currently available. In that case we call writeLock() to block the current thread until a write lock is available.

Regarding the case where tryConvertToWriteLock() fails, did I miss something or is the author acquiring a read-lock, followed by a write-lock, and never releasing the read-lock?

Further, won't lock.writeLock() deadlock waiting for the current thread to release its read-lock?

like image 660
Gili Avatar asked Mar 11 '18 04:03

Gili


People also ask

What is read lock in Java?

A ReadWriteLock maintains a pair of associated locks , one for read-only operations and one for writing. The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.


1 Answers

I believe the code sample provided by the article is buggy. According to https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/locks/StampedLock.html

Like Semaphore, but unlike most Lock implementations, StampedLocks have no notion of ownership. Locks acquired in one thread can be released or converted in another.

Further, they provide the following sample code:

void moveIfAtOrigin(double newX, double newY) { // upgrade
    // Could instead start with optimistic, not read mode
    long stamp = sl.readLock();
    try {
        while (x == 0.0 && y == 0.0) {
            long ws = sl.tryConvertToWriteLock(stamp);
            if (ws != 0L) {
                stamp = ws;
                x = newX;
                y = newY;
                break;
            }
            else {
                sl.unlockRead(stamp);
                stamp = sl.writeLock();
            }
        }
    } finally {
        sl.unlock(stamp);
    }
}

Notice how they release the read-lock before acquiring a write-lock.

like image 186
Gili Avatar answered Nov 15 '22 00:11

Gili