@Test
  public void testEvictingBlockCachingBlockGettingBlockConcurrently() throws Exception {
    ByteBuffAllocator byteBuffAllocator =
      ByteBuffAllocator.create(HBaseConfiguration.create(), true);
    final MyBucketCache2 myBucketCache2 = createMyBucketCache2(1, 1000);
    try {
      final HFileBlock hfileBlock = createBlock(200, 1020, byteBuffAllocator);
      final BlockCacheKey blockCacheKey = createKey("testThreeThreadConcurrent", 200);
      final AtomicReference<Throwable> cacheBlockThreadExceptionRef =
        new AtomicReference<Throwable>();
      Thread cacheBlockThread = new Thread(() -> {
        try {
          myBucketCache2.cacheBlock(blockCacheKey, hfileBlock);
          /**
           * Wait for Caching Block completed.
           */
          myBucketCache2.writeThreadDoneCyclicBarrier.await();
        } catch (Throwable exception) {
          cacheBlockThreadExceptionRef.set(exception);
        }
      });
      cacheBlockThread.setName(MyBucketCache2.CACHE_BLOCK_THREAD_NAME);
      cacheBlockThread.start();

      final AtomicReference<Throwable> evictBlockThreadExceptionRef =
        new AtomicReference<Throwable>();
      Thread evictBlockThread = new Thread(() -> {
        try {
          myBucketCache2.evictBlock(blockCacheKey);
        } catch (Throwable exception) {
          evictBlockThreadExceptionRef.set(exception);
        }
      });
      evictBlockThread.setName(MyBucketCache2.EVICT_BLOCK_THREAD_NAME);
      evictBlockThread.start();

      String oldThreadName = Thread.currentThread().getName();
      HFileBlock gotHFileBlock = null;
      try {
        Thread.currentThread().setName(MyBucketCache2.GET_BLOCK_THREAD_NAME);
        gotHFileBlock = (HFileBlock) (myBucketCache2.getBlock(blockCacheKey, false, false, false));
        assertTrue(gotHFileBlock.equals(hfileBlock));
        assertTrue(gotHFileBlock.getByteBuffAllocator() == byteBuffAllocator);
        assertEquals(2, gotHFileBlock.refCnt());
        try {
          /**
           * Release the second cyclicBarrier.await in {@link MyBucketCache2#putIntoBackingMap} for
           * {@link BucketCache.WriterThread},getBlock completed,{@link BucketCache.WriterThread}
           * could continue.
           */
          myBucketCache2.putCyclicBarrier.await();
        } catch (Throwable e) {
          throw new RuntimeException(e);
        }

      } finally {
        Thread.currentThread().setName(oldThreadName);
      }

      cacheBlockThread.join();
      evictBlockThread.join();
      assertTrue(cacheBlockThreadExceptionRef.get() == null);
      assertTrue(evictBlockThreadExceptionRef.get() == null);

      assertTrue(gotHFileBlock.equals(hfileBlock));
      assertEquals(1, gotHFileBlock.refCnt());
      assertTrue(myBucketCache2.overwiteByteBuff == null);
      assertTrue(myBucketCache2.freeBucketEntryCounter.get() == 0);

      gotHFileBlock.release();
      assertEquals(0, gotHFileBlock.refCnt());
      assertTrue(myBucketCache2.overwiteByteBuff != null);
      assertTrue(myBucketCache2.freeBucketEntryCounter.get() == 1);
      assertTrue(myBucketCache2.blockEvictCounter.get() == 1);
    } finally {
      myBucketCache2.shutdown();
    }

  }
<pre>
This test also is for HBASE-26281,
test three threads for evicting Block,caching Block and getting Block
execute concurrently.
1. Thread1 caching Block1, stopping after {@link BucketCache.WriterThread#putIntoBackingMap},
   the {@link RefCnt} of Block1 is 1.
2. Thread2 invoking {@link BucketCache#evictBlock} with the same {@link BlockCacheKey},
   but stopping after {@link BucketCache#removeFromRamCache}.
3. Thread3 invoking {@link BucketCache#getBlock} with the same {@link BlockCacheKey},
   which returned Block1, the {@link RefCnt} of Block1 is 2.
4. Thread1 continues caching block1,but finding that {@link BucketCache.RAMCache#remove}
   returning false, so invoking {@link BucketCache#blockEvicted} to free the the Block1
   directly which {@link RefCnt} is 2 and the Block1 is still used by Thread3.
</pre>
hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCacheRefCnt.java