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

1

7

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?

Pendulum answered 11/3, 2018 at 4:3 Comment(3)
The code above almost exactly matches the example code in the documentation, I'd assume you missed something. docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/…Overexert
@Overexert the documentation shows that when tryConvertToWriteLock() fails, the user releases the read-lock before acquiring a write-lock. The article does not release the read-lock.Pendulum
Interesting question. I looked at the code in grepcode and didn't find any evidence that tryConvertToWriteLock releases the read lock if it fails to acquire the write lock. Only if it is successful is the existing read lock upgraded. However I'm no expert on these low-level operations so I'm posting this as a comment instead of an answer. The fact that a "tutorial" contains such an error indicates how hard all this is.Quick
P
6

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.

Pendulum answered 11/3, 2018 at 4:26 Comment(1)
Fell into the same trap almost 3 years later.Asked the same question - https://mcmap.net/q/1623826/-java-8-stamped-lock-why-this-piece-of-code-doesnt-result-into-a-deadlock/3835632 Thanks to your answer.Kebab

© 2022 - 2024 — McMap. All rights reserved.