Program: 30982
Project: 30982
Buggy source:
@Test public void testLockBusyReader() throws Exception {
  final int readerCount=5;
  int threadCount=2;
  final int iterations=10000;
  final JournalMetadata<?>[] meta=new JournalMetadata[readerCount];
  for (int i=0; i < readerCount; i++) {
    final JournalMetadata<?> m=new JournalStructure("String_Node_Str" + i).$date("String_Node_Str").$().build();
    getWriterFactory().writer(m).close();
    meta[i]=m;
  }
  try {
    try (final CachingReaderFactory rf=new CachingReaderFactory(factoryContainer.getConfiguration(),1000,2)){
      final CyclicBarrier barrier=new CyclicBarrier(threadCount);
      final CountDownLatch halt=new CountDownLatch(threadCount);
      final AtomicInteger errors=new AtomicInteger();
      final LongList lockTimes=new LongList();
      final LongList workerTimes=new LongList();
      new Thread(){
        @Override public void run(){
          Rnd rnd=new Rnd();
          try {
            barrier.await();
            String name=null;
            for (int i=0; i < iterations; i++) {
              if (name == null) {
                name=meta[rnd.nextPositiveInt() % readerCount].getName();
              }
              while (true) {
                try {
                  rf.lock(name);
                  lockTimes.add(System.currentTimeMillis());
                  LockSupport.parkNanos(1L);
                  rf.unlock(name);
                  name=null;
                  break;
                }
 catch (                JournalException e) {
                  if (!(e instanceof RetryLockException)) {
                    e.printStackTrace();
                    errors.incrementAndGet();
                    break;
                  }
                }
              }
            }
          }
 catch (          Exception e) {
            e.printStackTrace();
            errors.incrementAndGet();
          }
          halt.countDown();
        }
      }
.start();
      new Thread(){
        @Override public void run(){
          Rnd rnd=new Rnd();
          workerTimes.add(System.currentTimeMillis());
          for (int i=0; i < iterations; i++) {
            JournalMetadata<?> metadata=meta[rnd.nextPositiveInt() % readerCount];
            try (Journal<?> ignored=rf.reader(metadata)){
              if (metadata == meta[readerCount - 1] && barrier.getNumberWaiting() > 0) {
                barrier.await();
              }
              LockSupport.parkNanos(1L);
            }
 catch (            JournalLockedException ignored) {
            }
catch (            Exception e) {
              e.printStackTrace();
              errors.incrementAndGet();
            }
          }
          workerTimes.add(System.currentTimeMillis());
          halt.countDown();
        }
      }
.start();
      halt.await();
      Assert.assertEquals(0,errors.get());
      int count=0;
      Assert.assertEquals(2,workerTimes.size());
      long lo=workerTimes.get(0);
      long hi=workerTimes.get(1);
      Assert.assertTrue(lockTimes.size() > 0);
      for (int i=0, n=lockTimes.size(); i < n; i++) {
        long t=lockTimes.getQuick(i);
        if (t > lo && t < hi) {
          count++;
        }
      }
      Assert.assertTrue(count > 0);
    }
   }
 catch (  Throwable e) {
    e.printStackTrace();
  }
}

Fixed version (ground truth):
@Test public void testLockBusyReader() throws Exception {
  final int readerCount=5;
  int threadCount=2;
  final int iterations=10000;
  final JournalMetadata<?>[] meta=new JournalMetadata[readerCount];
  for (int i=0; i < readerCount; i++) {
    final JournalMetadata<?> m=new JournalStructure("String_Node_Str" + i).$date("String_Node_Str").$().build();
    getWriterFactory().writer(m).close();
    meta[i]=m;
  }
  try {
    try (final CachingReaderFactory rf=new CachingReaderFactory(factoryContainer.getConfiguration(),1000,2)){
      final CyclicBarrier barrier=new CyclicBarrier(threadCount);
      final CountDownLatch halt=new CountDownLatch(threadCount);
      final AtomicInteger errors=new AtomicInteger();
      final LongList lockTimes=new LongList();
      final LongList workerTimes=new LongList();
      new Thread(){
        @Override public void run(){
          Rnd rnd=new Rnd();
          try {
            barrier.await();
            String name=null;
            for (int i=0; i < iterations; i++) {
              if (name == null) {
                name=meta[rnd.nextPositiveInt() % readerCount].getName();
              }
              while (true) {
                try {
                  rf.lock(name);
                  lockTimes.add(System.currentTimeMillis());
                  LockSupport.parkNanos(100L);
                  rf.unlock(name);
                  name=null;
                  break;
                }
 catch (                JournalException e) {
                  if (!(e instanceof RetryLockException)) {
                    e.printStackTrace();
                    errors.incrementAndGet();
                    break;
                  }
                }
              }
            }
          }
 catch (          Exception e) {
            e.printStackTrace();
            errors.incrementAndGet();
          }
          halt.countDown();
        }
      }
.start();
      new Thread(){
        @Override public void run(){
          Rnd rnd=new Rnd();
          workerTimes.add(System.currentTimeMillis());
          for (int i=0; i < iterations; i++) {
            JournalMetadata<?> metadata=meta[rnd.nextPositiveInt() % readerCount];
            try (Journal<?> ignored=rf.reader(metadata)){
              if (metadata == meta[readerCount - 1] && barrier.getNumberWaiting() > 0) {
                barrier.await();
              }
              LockSupport.parkNanos(10L);
            }
 catch (            JournalLockedException ignored) {
            }
catch (            Exception e) {
              e.printStackTrace();
              errors.incrementAndGet();
            }
          }
          workerTimes.add(System.currentTimeMillis());
          halt.countDown();
        }
      }
.start();
      halt.await();
      Assert.assertEquals(0,errors.get());
      int count=0;
      Assert.assertEquals(2,workerTimes.size());
      long lo=workerTimes.get(0);
      long hi=workerTimes.get(1);
      Assert.assertTrue(lockTimes.size() > 0);
      for (int i=0, n=lockTimes.size(); i < n; i++) {
        long t=lockTimes.getQuick(i);
        if (t > lo && t < hi) {
          count++;
        }
      }
      Assert.assertTrue(count > 0);
    }
   }
 catch (  Throwable e) {
    e.printStackTrace();
  }
}