[jbosscache-commits] JBoss Cache SVN: r7505 - core/trunk/src/test/java/org/jboss/cache/lock.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Mon Jan 19 04:42:32 EST 2009
Author: mircea.markus
Date: 2009-01-19 04:42:32 -0500 (Mon, 19 Jan 2009)
New Revision: 7505
Modified:
core/trunk/src/test/java/org/jboss/cache/lock/ReadWriteLockWithUpgradeTest.java
Log:
more strict threading control
Modified: core/trunk/src/test/java/org/jboss/cache/lock/ReadWriteLockWithUpgradeTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/lock/ReadWriteLockWithUpgradeTest.java 2009-01-18 19:36:17 UTC (rev 7504)
+++ core/trunk/src/test/java/org/jboss/cache/lock/ReadWriteLockWithUpgradeTest.java 2009-01-19 09:42:32 UTC (rev 7505)
@@ -8,6 +8,7 @@
import java.util.Vector;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;
/**
@@ -82,183 +83,214 @@
* <p/>
* Each test case should also call cleanLockingResult() to reset
* result vector for the next test cases.
- *
- * @param caseNum Arbitrary string for the test case number.
- * @param name Arbitrary string for the calling thread name.
- * @param msecs Milliseconds that the thread should sleep after
- * acquiring the read lock.
- * @param errMsg Error msg to log in case of error.
- * @param secondOP Set to NO_MORE_OP if a 2nd lock request is not required.
- * Set to INVOKE_READ, INVOKE_READ or INVOKE_UPGRADE
- * respectively if the 2nd lock is a read, write or
- * upgrade request respectively.
*/
- protected Thread readThread(final String caseNum, final String name,
- final long msecs, final long sleepSecs,
- final String errMsg, final int secondOP)
+ class ReadThread extends Thread
{
- return new Thread(name)
- {
- public void run()
- {
- Lock rlock = lock_.readLock();
- try
- {
- if (!rlock.tryLock(msecs, TimeUnit.MILLISECONDS))
- {
- String str = caseNum + "-" + name + "-RL-0";
- postLockingResult(str);
- return;
- }
- // OK, read lock obtained, sleep and release it.
- String str = caseNum + "-" + name + "-RL-1";
- postLockingResult(str);
- TestingUtil.sleepThread(sleepSecs);
- if (secondOP == INVOKE_READ)
- {
- acquireReadLock(caseNum, name, msecs, errMsg);
- }
- else if (secondOP == INVOKE_WRITE)
- {
- acquireWriteLock(caseNum, name, msecs, errMsg);
- }
- else if (secondOP == INVOKE_UPGRADE)
- {
- acquireUpgradeLock(caseNum, name, msecs, errMsg);
- }
+ private String caseNum;
+ private String name;
+ volatile CountDownLatch notifyBeforeSecondOp = new CountDownLatch(1);
+ volatile CountDownLatch notifyBeforeFinish = new CountDownLatch(1);
+ volatile CountDownLatch waitLatch;
+ private String errMsg;
+ private int secondOP;
- rlock.unlock();
- }
- catch (Exception ex)
- {
- }
- }
- };
- }
+ ReadThread(String caseNum, String name, String errMsg, int secondOP, CountDownLatch waitLatch) {
+ this.caseNum = caseNum;
+ this.name = name;
+ this.errMsg = errMsg;
+ this.secondOP = secondOP;
+ this.waitLatch = waitLatch;
+ }
- /**
- * Creates a new thread and acquires a write lock with a timeout
- * value specified by the caller. Similar to {@link #readThread readThread()}
- * except it's used for write locks.
- *
- * @see #readThread readThread()
- */
- protected Thread writeThread(final String caseNum, final String name,
- final long msecs, final long sleepSecs,
- final String errMsg, final int secondOP)
- {
- return new Thread(name)
- {
- public void run()
- {
- try
- {
- Lock wlock = lock_.writeLock();
- if (!wlock.tryLock(msecs, TimeUnit.MILLISECONDS))
- {
- String str = caseNum + "-" + name + "-WL-0";
- postLockingResult(str);
- return;
- }
- // OK, write lock obtained, sleep and release it.
- String str = caseNum + "-" + name + "-WL-1";
- postLockingResult(str);
- TestingUtil.sleepThread(sleepSecs);
+ public void run()
+ {
+ Lock rlock = lock_.readLock();
+ try
+ {
+ if (!rlock.tryLock(0, TimeUnit.MILLISECONDS))
+ {
+ String str = caseNum + "-" + name + "-RL-0";
+ postLockingResult(str);
+ processNotifications();
+ return;
+ }
+ // OK, read lock obtained, sleep and release it.
+ String str = caseNum + "-" + name + "-RL-1";
+ postLockingResult(str);
+ processNotifications();
- if (secondOP == INVOKE_READ)
- {
- acquireReadLock(caseNum, name, msecs, errMsg);
- }
- else if (secondOP == INVOKE_WRITE)
- {
- acquireWriteLock(caseNum, name, msecs, errMsg);
- }
- else if (secondOP == INVOKE_UPGRADE)
- {
- acquireUpgradeLock(caseNum, name, msecs, errMsg);
- }
+ if (secondOP == INVOKE_READ)
+ {
+ acquireReadLock(caseNum, name, errMsg);
+ }
+ else if (secondOP == INVOKE_WRITE)
+ {
+ acquireWriteLock(caseNum, name, errMsg);
+ }
+ else if (secondOP == INVOKE_UPGRADE)
+ {
+ acquireUpgradeLock(caseNum, name, errMsg);
+ }
+ rlock.unlock();
+ notifyBeforeFinish.countDown();
+ }
+ catch (Exception ex)
+ {
+ }
+ }
- wlock.unlock();
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
- };
+ private void processNotifications() throws InterruptedException {
+ notifyBeforeSecondOp.countDown();
+ if (waitLatch != null) waitLatch.await(10, TimeUnit.SECONDS);
+ }
}
- /**
- * Creates a new thread, acquires a read lock, sleeps for a while
- * and then tries to upgrade the read lock to a write one. Similar
- * to {@link #readThread readThread()} except it's used for upgrading
- * locks.
- *
- * @see #readThread readThread()
- */
- protected Thread upgradeThread(final String caseNum, final String name,
- final long msecs, final String errMsg)
- {
- return new Thread(name)
- {
- public void run()
- {
- try
- {
- Lock rlock = lock_.readLock();
- Lock wlock = null;
- if (!rlock.tryLock(msecs, TimeUnit.MILLISECONDS))
- {
- String str = caseNum + "-" + name + "-RL-0";
- postLockingResult(str);
- return;
- }
- // OK, read lock obtained, sleep and upgrade it later.
- TestingUtil.sleepThread(SLEEP_MSECS / 2);
- String str = caseNum + "-" + name + "-UL-";
- if ((wlock = lock_.upgradeLockAttempt(msecs)) == null)
- {
- str += "0";
- }
- else
- {
- str += "1";
- }
- postLockingResult(str);
- // Sleep again and then release the lock.
- TestingUtil.sleepThread(SLEEP_MSECS);
- if (wlock != null)
- {
- wlock.unlock();
- }
- rlock.unlock();
- }
- catch (Exception ex)
- {
- }
- }
- };
- }
+ private class WriteThread extends Thread
+ {
+ String caseNum;
+ String name;
+ volatile CountDownLatch notifyLatch = new CountDownLatch(1);
+ volatile CountDownLatch waitLatch;
+ String errMsg;
+ int secondOP;
+ WriteThread(String caseNum, String name, String errMsg, int secondOP, CountDownLatch waitLatch) {
+ this.caseNum = caseNum;
+ this.name = name;
+ this.errMsg = errMsg;
+ this.secondOP = secondOP;
+ this.waitLatch = waitLatch;
+ }
+
+
+ public void run()
+ {
+ try
+ {
+ Lock wlock = lock_.writeLock();
+ if (!wlock.tryLock(0, TimeUnit.MILLISECONDS))
+ {
+ String str = caseNum + "-" + name + "-WL-0";
+ postLockingResult(str);
+ processNotifications();
+ return;
+ }
+ // OK, write lock obtained, sleep and release it.
+ String str = caseNum + "-" + name + "-WL-1";
+ postLockingResult(str);
+
+ processNotifications();
+
+ if (secondOP == INVOKE_READ)
+ {
+ acquireReadLock(caseNum, name, errMsg);
+ }
+ else if (secondOP == INVOKE_WRITE)
+ {
+ acquireWriteLock(caseNum, name, errMsg);
+ }
+ else if (secondOP == INVOKE_UPGRADE)
+ {
+ acquireUpgradeLock(caseNum, name, errMsg);
+ }
+
+ wlock.unlock();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ private void processNotifications() throws InterruptedException {
+ notifyLatch.countDown();
+ if (waitLatch != null)
+ waitLatch.await(10, TimeUnit.SECONDS);
+ }
+ }
+
+ class UpgradeThread extends Thread
+ {
+ String caseNum;
+ String name;
+ private CountDownLatch notifyBeforeFinish = new CountDownLatch(1);
+ private CountDownLatch notifyBeforeSecondOp = new CountDownLatch(1);
+ private CountDownLatch beforeUpgrateWait;
+ private CountDownLatch beforeFinishWait;
+ String errMsg;
+ int secondOP;
+
+ UpgradeThread(String caseNum, String name, String errMsg, int secondOP, CountDownLatch beforeUpgrateWait) {
+ this.caseNum = caseNum;
+ this.name = name;
+ this.errMsg = errMsg;
+ this.secondOP = secondOP;
+ this.beforeUpgrateWait = beforeUpgrateWait;
+ }
+
+ public void run()
+ {
+ try
+ {
+ Lock rlock = lock_.readLock();
+ Lock wlock;
+ if (!rlock.tryLock(0, TimeUnit.MILLISECONDS))
+ {
+ String str = caseNum + "-" + name + "-RL-0";
+ postLockingResult(str);
+ notifyBeforeFinish.countDown();
+ if (beforeUpgrateWait != null) beforeUpgrateWait.await(10, TimeUnit.SECONDS);
+ return;
+ }
+ // OK, read lock obtained, sleep and upgrade it later.
+ notifyBeforeSecondOp.countDown();
+ if (beforeUpgrateWait != null) beforeUpgrateWait.await(10, TimeUnit.SECONDS);
+ String str = caseNum + "-" + name + "-UL-";
+ if ((wlock = lock_.upgradeLockAttempt(0)) == null)
+ {
+ str += "0";
+ }
+ else
+ {
+ str += "1";
+ }
+ postLockingResult(str);
+ // Sleep again and then release the lock.
+ TestingUtil.sleepThread(SLEEP_MSECS);
+ if (wlock != null)
+ {
+ wlock.unlock();
+ }
+ rlock.unlock();
+ notifyBeforeFinish.countDown();
+ if (beforeFinishWait != null) beforeFinishWait.await(10, TimeUnit.SECONDS);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+
+ }
+
+
/***************************************************************/
/* Utility functions to acquire RL and WL (no thread) */
/***************************************************************/
/**
* This routine tries to acquire a read lock with a timeout value
- * passed in by the caller. Like {@link #readThread readThread()}
- * it then stores the locking result in the result vector depending
+ * passed in by the caller. It then stores the locking result in the result vector depending
* on the outcome of the request.
*/
protected void acquireReadLock(final String caseNum, final String name,
- final long msecs, final String errMsg)
+ final String errMsg)
{
try
{
Lock rlock = lock_.readLock();
- if (!rlock.tryLock(msecs, TimeUnit.MILLISECONDS))
+ if (!rlock.tryLock(0, TimeUnit.MILLISECONDS))
{
String str = caseNum + "-" + name + "-RL-0";
postLockingResult(str);
@@ -279,13 +311,12 @@
* Same as {@link #acquireReadLock acquireReadLock()} except
* it's for write lock request.
*/
- protected void acquireWriteLock(final String caseNum, final String name,
- final long msecs, final String errMsg)
+ protected void acquireWriteLock(final String caseNum, final String name, final String errMsg)
{
try
{
Lock wlock = lock_.writeLock();
- if (!wlock.tryLock(msecs, TimeUnit.MILLISECONDS))
+ if (!wlock.tryLock(0, TimeUnit.MILLISECONDS))
{
String str = caseNum + "-" + name + "-WL-0";
postLockingResult(str);
@@ -307,12 +338,12 @@
* it's for upgrade lock request.
*/
protected void acquireUpgradeLock(final String caseNum, final String name,
- final long msecs, final String errMsg)
+ final String errMsg)
{
try
{
Lock ulock = null;
- if ((ulock = lock_.upgradeLockAttempt(msecs)) == null)
+ if ((ulock = lock_.upgradeLockAttempt(0)) == null)
{
String str = caseNum + "-" + name + "-UL-0";
postLockingResult(str);
@@ -378,10 +409,8 @@
public void testWriteWithMultipleReaders() throws Exception
{
String caseNum = "10";
- Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS * 2,
- "1st read lock attempt failed", NO_MORE_OP);
- Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS,
- "2nd read lock attempt failed", INVOKE_WRITE);
+ ReadThread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", NO_MORE_OP, null);
+ ReadThread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", INVOKE_WRITE, t1.notifyBeforeSecondOp);
t1.start();
t2.start();
@@ -404,10 +433,8 @@
public void testUpgradeWithMultipleReadersOn1() throws Exception
{
String caseNum = "11";
- Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
- "1st read lock attempt failed", INVOKE_WRITE);
- Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS * 2,
- "2nd read lock attempt failed", NO_MORE_OP);
+ ReadThread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", INVOKE_WRITE, null);
+ ReadThread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", NO_MORE_OP, t1.notifyBeforeSecondOp);
t1.start();
t2.start();
@@ -430,8 +457,7 @@
public void testUpgradeReadLock() throws Exception
{
String caseNum = "2";
- Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
- "1st read lock attempt failed", INVOKE_UPGRADE);
+ Thread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", INVOKE_UPGRADE, null);
t1.start();
t1.join(3000);
@@ -443,12 +469,11 @@
/**
* Case #3 - T1 acquires RL followed by WL.
*/
-
public void testReadThenWrite() throws Exception
{
String caseNum = "3";
- acquireReadLock(caseNum, "t1", 0, "1st read lock attempt failed");
- acquireWriteLock(caseNum, "t1.1", 0, "2nd write lock attempt failed");
+ acquireReadLock(caseNum, "t1", "1st read lock attempt failed");
+ acquireWriteLock(caseNum, "t1.1", "2nd write lock attempt failed");
assertTrue(checkLockingResult(caseNum + "-t1-RL-1") &&
checkLockingResult(caseNum + "-t1.1-WL-1"));
cleanLockingResult();
@@ -458,12 +483,11 @@
/**
* Case #5 - T1 acquires WL followed by RL.
*/
-
public void testWriteThenRead() throws Exception
{
String caseNum = "5";
- acquireWriteLock(caseNum, "t1", 0, "1st write lock attempt failed");
- acquireReadLock(caseNum, "t1.1", 0, "2nd read lock attempt failed");
+ acquireWriteLock(caseNum, "t1", "1st write lock attempt failed");
+ acquireReadLock(caseNum, "t1.1", "2nd read lock attempt failed");
assertTrue(checkLockingResult(caseNum + "-t1-WL-1") &&
checkLockingResult(caseNum + "-t1.1-RL-1"));
cleanLockingResult();
@@ -475,10 +499,8 @@
public void testMultipleReadlock() throws Exception
{
String caseNum = "6";
- Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
- "1st read lock attempt failed", NO_MORE_OP);
- Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS,
- "2nd read lock attempt failed", NO_MORE_OP);
+ Thread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", NO_MORE_OP, null);
+ Thread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", NO_MORE_OP, null);
t1.start();
t2.start();
@@ -500,16 +522,22 @@
public void testWriteWithExistingReader() throws Exception
{
String caseNum = "8";
- Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
- "1st write lock attempt failed", NO_MORE_OP);
- Thread t2 = writeThread(caseNum, "t2", 0, SLEEP_MSECS,
- "2nd read lock attempt failed", NO_MORE_OP);
+ CountDownLatch waitFor = new CountDownLatch(1);
+ ReadThread t1 = new ReadThread(caseNum, "t1", "1st write lock attempt failed", NO_MORE_OP, waitFor);
+ WriteThread t2 = new WriteThread(caseNum, "t2", "2nd read lock attempt failed", NO_MORE_OP, waitFor);
t1.start();
t2.start();
+
+ t1.notifyBeforeSecondOp.await();
+ t2.notifyLatch.await();
+ waitFor.countDown();
+
+ waitFor.countDown();
t1.join(3000);
t2.join(3000);
+
// there is NO guarantee as to which thread will get the lock!!
boolean t0GetsLock = checkLockingResult(caseNum + "-t1-RL-1") && checkLockingResult(caseNum + "-t2-WL-0");
boolean t1GetsLock = checkLockingResult(caseNum + "-t1-RL-0") && checkLockingResult(caseNum + "-t2-WL-1");
@@ -531,13 +559,17 @@
public void testReadWithExistingWriter() throws Exception
{
String caseNum = "13";
- Thread t1 = writeThread(caseNum, "t1", 0, SLEEP_MSECS,
- "1st write lock attempt failed", NO_MORE_OP);
- Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS,
- "2nd read lock attempt failed", NO_MORE_OP);
+ CountDownLatch waitFor = new CountDownLatch(1);
+ WriteThread t1 = new WriteThread(caseNum, "t1", "1st write lock attempt failed", NO_MORE_OP, waitFor);
+ ReadThread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", NO_MORE_OP, waitFor);
t1.start();
t2.start();
+
+ t1.notifyLatch.await();
+ t2.notifyBeforeSecondOp.await();
+ waitFor.countDown();
+
t1.join(3000);
t2.join(3000);
@@ -562,13 +594,16 @@
public void testMultipleWritelocks() throws Exception
{
String caseNum = "14";
- Thread t1 = writeThread(caseNum, "t1", 0, SLEEP_MSECS,
- "1st write lock attempt failed", NO_MORE_OP);
- Thread t2 = writeThread(caseNum, "t2", 0, SLEEP_MSECS,
- "2nd write lock attempt failed", NO_MORE_OP);
+ CountDownLatch waitFor = new CountDownLatch(1);
+ WriteThread t1 = new WriteThread(caseNum, "t1", "1st write lock attempt failed", NO_MORE_OP, waitFor);
+ WriteThread t2 = new WriteThread(caseNum, "t2", "2nd write lock attempt failed", NO_MORE_OP, waitFor);
t1.start();
t2.start();
+ t1.notifyLatch.await();
+ t2.notifyLatch.await();
+ waitFor.countDown();
+
t1.join(3000);
t2.join(3000);
@@ -590,21 +625,23 @@
/**
* Case #7 - T1 acquires RL, T2 acquires UL.
*/
-
public void testUpgradeWithExistingReader() throws Exception
{
String caseNum = "7";
- Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
- "1st read lock attempt failed", NO_MORE_OP);
- Thread t2 = upgradeThread(caseNum, "t2", 0,
- "2nd upgrade lock attempt failed");
+ CountDownLatch waitFor = new CountDownLatch(1);
+ ReadThread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", NO_MORE_OP, waitFor);
+ UpgradeThread t2 = new UpgradeThread(caseNum, "t2", "2nd upgrade lock attempt failed", NO_MORE_OP, t1.notifyBeforeSecondOp);
+ t2.beforeFinishWait = waitFor;
t1.start();
t2.start();
+ t2.notifyBeforeFinish.await(10, TimeUnit.SECONDS);
+ waitFor.countDown();
+
t1.join(3000);
t2.join(3000);
- assertTrue(checkLockingResult(caseNum + "-t1-RL-1") &&
- checkLockingResult(caseNum + "-t2-UL-0"));
+ assertTrue(checkLockingResult(caseNum + "-t1-RL-1"));
+ assertTrue(checkLockingResult(caseNum + "-t2-UL-0"));
cleanLockingResult();
// possilbe deadlock check
if (t1.isAlive() || t2.isAlive())
@@ -619,13 +656,17 @@
public void testUpgradeWithMultipleReaders() throws Exception
{
String caseNum = "9";
- Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS * 2,
- "1st read lock attempt failed", NO_MORE_OP);
- Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS,
- "2nd read lock attempt failed", INVOKE_UPGRADE);
+ CountDownLatch waitFor = new CountDownLatch(1);
+ ReadThread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", NO_MORE_OP, waitFor);
+ ReadThread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", INVOKE_UPGRADE, t1.notifyBeforeSecondOp);
t1.start();
t2.start();
+
+ t1.notifyBeforeSecondOp.await(10, TimeUnit.SECONDS);
+ t2.notifyBeforeFinish.await(10, TimeUnit.SECONDS);
+ waitFor.countDown();
+
t1.join(3000);
t2.join(3000);
assertTrue(checkLockingResult(caseNum + "-t1-RL-1") &&
More information about the jbosscache-commits
mailing list