@Test public void testReadWriteDeadlock() throws Exception {
    System.out.println("testReadWriteDeadlock constructing deadlock:");

    LockGrabber lg1Read = startGrabber(tid1, p0, Permissions.READ_ONLY);
    LockGrabber lg2Read = startGrabber(tid2, p1, Permissions.READ_ONLY);

    // allow read locks to acquire
    Thread.sleep(POLL_INTERVAL);

    LockGrabber lg1Write = startGrabber(tid1, p1, Permissions.READ_WRITE);
    LockGrabber lg2Write = startGrabber(tid2, p0, Permissions.READ_WRITE);

    while (true) {
      Thread.sleep(POLL_INTERVAL);

      assertFalse(lg1Write.acquired() && lg2Write.acquired());
      if (lg1Write.acquired() && !lg2Write.acquired()) break;
      if (!lg1Write.acquired() && lg2Write.acquired()) break;

      if (lg1Write.getError() != null) {
        lg1Read.stop(); lg1Write.stop();
        bp.transactionComplete(tid1);
        Thread.sleep(rand.nextInt(WAIT_INTERVAL));

        tid1 = new TransactionId();
        lg1Read = startGrabber(tid1, p0, Permissions.READ_ONLY);
        lg1Write = startGrabber(tid1, p1, Permissions.READ_WRITE);
      }

      if (lg2Write.getError() != null) {
        lg2Read.stop(); lg2Write.stop();
        bp.transactionComplete(tid2);
        Thread.sleep(rand.nextInt(WAIT_INTERVAL));

        tid2 = new TransactionId();
        lg2Read = startGrabber(tid2, p1, Permissions.READ_ONLY);
        lg2Write = startGrabber(tid2, p0, Permissions.READ_WRITE);
      }
    }

    System.out.println("testReadWriteDeadlock resolved deadlock");
  }