code: public Element<T> get() {
          // start at a random index, so different threads don't all start at index 0 and compete for the lock
          int starting_index=((int)(Math.random() * pool.length)) & (pool.length - 1);
          for(int i=0; i < locks.length; i++) {
              int index=(starting_index + i) & (pool.length -1);
              Lock lock=locks[index];
              if(lock.tryLock()) {
                  if(pool[index] != null)
                      return new Element<>(pool[index], lock);
                  return new Element<>(pool[index]=creator.get(), lock);
              }
          }
          return new Element<>(creator.get(), null);
      }
docs: Gets the next available resource for which the lock can be acquired and returns it and its associated
  lock, which needs to be released when the caller is done using the resource. If no resource in the pool can be
  locked, returns a newly created resource and a null lock. This means that no lock was acquired and thus
  doesn't need to be released.
  @return An Element with T and a lock (possibly null if newly created)