code: private <T> T executeWithGlobalLock(final Job<T> job, final boolean _checkClosed) {
      synchronized (lock) {
        if (_checkClosed) { checkClosed(); }
        eviction.stop();
        try {
          T _result = hash.runTotalLocked(new Job<T>() {
            @Override
            public T call() {
              if (_checkClosed) { checkClosed(); }
              boolean f = eviction.drain();
              if (f) {
                return (T) RESTART_AFTER_EVICTION;
              }
              return eviction.runLocked(new Job<T>() {
                @Override
                public T call() {
                  return job.call();
                }
              });
            }
          });
          if (_result == RESTART_AFTER_EVICTION) {
            eviction.evictEventually();
            _result = hash.runTotalLocked(new Job<T>() {
              @Override
              public T call() {
                if (_checkClosed) { checkClosed(); }
                eviction.drain();
                return eviction.runLocked(new Job<T>() {
                  @Override
                  public T call() {
                    return job.call();
                  }
                });
              }
            });
          }
          return _result;
        } finally {
          eviction.start();
        }
      }
    }
docs: Execute job while making sure that no other operations are going on.
  In case the eviction is connected via a queue we need to stop the queue processing.
  On the other hand we needs to make sure that the queue is drained because this
  method is used to access the recent statistics or check integrity. Draining the queue
  is a two phase job: The draining may not do eviction since we hold the locks, after
  lifting the lock with do eviction and lock again. This ensures that all
  queued entries are processed up to the point when the method was called.
  
  @param _checkClosed variant, this method is needed once without check during the close itself