Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to to use StampedLock optimistic locking ?(I can't understand code sample from java doc)

Recently I learned about the existence StampedLock ?

https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/locks/StampedLock.html I realized that It is improved ReentrantReadWriteLock with some differernces:

  • Is not reentrant
  • Supports optomistic lock
  • Supports upgrade from readLock to writeLock

Also I read examples frpm javadoc but I don't understant that code:

class Point {
  private double x, y;
  private final StampedLock sl = new StampedLock();
  // a read-only method
  // upgrade from optimistic read to read lock
  double distanceFromOrigin() {
    long stamp = sl.tryOptimisticRead();
    try {
      retryHoldingLock: for (;; stamp = sl.readLock()) {
        if (stamp == 0L)
          continue retryHoldingLock;
        // possibly racy reads
        double currentX = x;
        double currentY = y;
        if (!sl.validate(stamp))
          continue retryHoldingLock;
        return Math.hypot(currentX, currentY);
      }
    } finally {
      if (StampedLock.isReadLockStamp(stamp))
        sl.unlockRead(stamp);
    }
  }
}

What does it mean possibly racy reads ? [ANSWERRED IN COMMENTS]

Is it a problem if another thread reads x or y ? [ANSWERRED IN COMMENTS]

why do we execute tryOptimisticRead first and readLock in the for loop in case of tryOptimisticRead failure? what the logic?

Why do we have if (StampedLock.isReadLockStamp(stamp)) inside finally block vbefore unlock ?

like image 363
gstackoverflow Avatar asked Dec 22 '22 23:12

gstackoverflow


1 Answers

why do we execute tryOptimisticRead first and readLock in the for loop in case of tryOptimisticRead failure? what the logic?

A best case scenario is for us to to be able to read x and y without having to acquire a lock. That doesn't mean we don't establish a happens-before relationship, it just means we don't need to invoke a possible blocking action.

tryOptimisticRead returns us a stamp value. This volatile read of internal state establishes that anything written prior to the volatile write of this stamped value will be visible after a subsequent read. That means, if the stamped value returned in tryOptimisticRead doesn't change while you read x and y, then another write did not occur and we have the most up to date values. If the stamped value does change, however, all bets are off and you need to protect yourself explained below.

It's possible, and, depending on your use case, likely, that x and y will change at some point throughout your execution of distanceFromOrigin. If x and y change, and maybe change often, you're going to want to eventually succeed.

The readLock is the program's way of saying "Ok, I give up, let's just read it in a blocking fashion". In theory, you can write your code to tryOptimisticRead a few times before eventually invoking readLock, but you're going to want to give yourself an out in case x and y are updated constantly.

Why do we have if (StampedLock.isReadLockStamp(stamp)) inside finally block vbefore unlock ?

If readLock is invoked, you will have to release it prior to exiting so that subsequent writeLock can acquire the lock. If you succeed in tryOptimisticRead you will not have to release a readLock as you never needed to acquire it in the first place.

like image 89
John Vint Avatar answered Jan 07 '23 10:01

John Vint