@Override
 public boolean isLockedBy(Data key, String caller, long threadId) {
   LockResource lock = locks.get(key);
   if (lock == null) {
     return false;
   }
   return lock.isLockedBy(caller, threadId);
 }
 @Override
 public String getOwnerInfo(Data key) {
   final LockResource lock = locks.get(key);
   if (lock == null) {
     return "<not-locked>";
   } else {
     return "Owner: " + lock.getOwner() + ", thread-id: " + lock.getThreadId();
   }
 }
 @Override
 public long getRemainingLeaseTime(Data key) {
   LockResource lock = locks.get(key);
   if (lock == null) {
     return -1L;
   } else {
     return lock.getRemainingLeaseTime();
   }
 }
 @Override
 public int getLockCount(Data key) {
   LockResource lock = locks.get(key);
   if (lock == null) {
     return 0;
   } else {
     return lock.getLockCount();
   }
 }
 @Override
 public Set<Data> getLockedKeys() {
   Set<Data> keySet = new HashSet<Data>(locks.size());
   for (Map.Entry<Data, LockResourceImpl> entry : locks.entrySet()) {
     Data key = entry.getKey();
     LockResource lock = entry.getValue();
     if (lock.isLocked()) {
       keySet.add(key);
     }
   }
   return keySet;
 }
 @Override
 public boolean isLocked(Data key) {
   LockResource lock = locks.get(key);
   return lock != null && lock.isLocked();
 }
    @Override
    public void run() {
      try {
        for (int i = 0; i < 100; i++) {
          int sharedBeforeChange = getSharedResource();
          int shared = -1;

          lock.lockShared();

          try {
            // do something needing write
            lock.lockExclusively();

            try {
              shared = getSharedResource() + 1;

              // do something
              Thread.sleep(rnd.nextInt(50));

              setSharedResource(shared);

              lock.lockShared();

              try {
                // do something
                Thread.sleep(rnd.nextInt(50));
              } finally {
                lock.unlock();
              }
            } finally {
              lock.unlock();
            }
          } finally {
            lock.unlock();
          }

          // kick other threads
          Thread.yield();

          // do something
          Thread.sleep(rnd.nextInt(50));

          // This code executes OUTSIDE of critical region!
          int sharedAfterChange = getSharedResource();

          // Assertion (note, it's STRICTLY LESS-THEN):
          // sharedBeforeChange < shared = sharedAfterChange
          if (!((sharedBeforeChange < shared) && (shared <= sharedAfterChange))) {
            throw new IllegalStateException(
                Thread.currentThread().getName()
                    + " before:"
                    + sharedBeforeChange
                    + " shared:"
                    + shared
                    + " after:"
                    + sharedAfterChange);
          }
        }
      } catch (InterruptedException e) {
        throw new IllegalStateException(e);
      }
    }