/**
   * https://issues.apache.org/jira/browse/WICKET-5316
   *
   * @throws Exception
   */
  @Test
  public void failToReleaseUnderLoad() throws Exception {
    final Duration duration = Duration.seconds(20); /* seconds */
    final ConcurrentLinkedQueue<Exception> errors = new ConcurrentLinkedQueue<Exception>();
    final long endTime = System.currentTimeMillis() + duration.getMilliseconds();

    // set the synchronizer timeout one second longer than the test runs to prevent
    // starvation to become an issue
    final PageAccessSynchronizer sync =
        new PageAccessSynchronizer(duration.add(Duration.ONE_SECOND));

    final CountDownLatch latch = new CountDownLatch(100);
    for (int count = 0; count < 100; count++) {
      new Thread() {
        @Override
        public void run() {
          try {
            while (System.currentTimeMillis() < endTime) {
              try {
                logger.debug(Thread.currentThread().getName() + " locking");
                sync.lockPage(0);
                Thread.sleep(1);
                logger.debug(Thread.currentThread().getName() + " locked");
                sync.unlockAllPages();
                logger.debug(Thread.currentThread().getName() + " unlocked");
                Thread.sleep(5);
              } catch (InterruptedException e) {
                throw new RuntimeException(e);
              }
            }
          } catch (Exception e) {
            logger.error(e.getMessage(), e);
            errors.add(e);
          } finally {
            latch.countDown();
          }
        }
      }.start();
    }
    latch.await();
    if (!errors.isEmpty()) {
      logger.error("Number of lock errors that occurred: {}", errors.size());
      throw errors.remove();
    }
  }
 /**
  * Construct a TimerChannelBehavior which actually refreshes the clients by polling the server for
  * changes at the given duration.
  *
  * @param updateInterval the interval at which the server should be polled for changes
  */
 public TimerChannelBehavior(final Duration updateInterval) {
   this(updateInterval, updateInterval.add(TIMEOUT_MARGIN));
 }