@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);
      }
    }