What is a good way to test that a Java method is synchronized? What is a good way to test that a Java method is synchronized? multithreading multithreading

What is a good way to test that a Java method is synchronized?


If you just want to check if a method has the synchronized modifier, aside from the obvious (looking at the source code/Javadoc), you can also use reflection.

Modifier.isSynchronized(method.getModifiers())

The more general question of testing if a method guarantees proper synchronization in all concurrency scenarios is likely to be an undecidable problem.


These are all horrible ideas, but you could do this...

1

    // Substitute this LOCK with your monitor (could be you object you are    // testing etc.)    final Object LOCK = new Object();    Thread locker = new Thread() {        @Override        public void run() {            synchronized (LOCK) {                try {                    Thread.sleep(Long.MAX_VALUE);                } catch (InterruptedException e) {                    System.out.println("Interrupted.");                    return;                }            }        }    };    locker.start();    Thread attempt = new Thread() {        @Override        public void run() {            // Do your test.        }    };    attempt.start();    try {        long longEnough = 3000 * 1000;// It's in nano seconds        long before = System.nanoTime();        attempt.join(longEnough);        long after = System.nanoTime();        if (after - before < longEnough) {            throw new AssertionError("FAIL");        } else {            System.out.println("PASS");        }    } catch (InterruptedException e) {        Thread.currentThread().interrupt();        return;    }    locker.interrupt();

2

If you know that methods on the arguments are always invoked in any implementation, you can pass a mock object that disguises as the argument and calls holdsLock().

So like:

class Mock implements Argument {    private final Object LOCK;    private final Argument real;    public Mock(Object obj, Argument real){       this.LOCK=obj;       this.real = real;    }    @Overrides    public void something(){        System.out.println("held:"+Thread.holdsLock(LOCK));        this.real.something();    }

Then wait for the class to invoke something() on Argument.


A big thank you to Zwei steinen for writing up the approach I used. There are a few problems in the example code that I worked through, so I thought it would be worth posting my findings here.

  • The call to join() expects a number of milliseconds, not nanoseconds.
  • The two threads must be coordinated, otherwise the attempt thread can start and finish all before the locker thread grabs the lock.
  • The attempt thread should not be started until after we record the start time. Otherwise that thread gets enough of a head start that the recorded time can be slightly less than the timeout, causing spurious failures.

Here is the synchronization test code as a Scala trait:

trait SynchronizedTestTrait{    val classUnderTest: AnyRef    class Gate    {        val latch = new java.util.concurrent.CountDownLatch(1)        def open()        {            this.latch.countDown        }        def await()        {            this.latch.await        }    }    def nanoTime(code: => Unit) =    {        val before = System.nanoTime        code        val after = System.nanoTime        after - before    }    def assertSynchronized(code: => Unit)    {        this.assertThreadSafety(threadSafe = true, millisTimeout = 10L)(code)    }    def assertNotSynchronized(code: => Unit)    {        this.assertThreadSafety(threadSafe = false, millisTimeout = 60L * 1000L)(code)    }    def assertThreadSafety(threadSafe: Boolean, millisTimeout: Long)(code: => Unit)    {        def spawn(code: => Unit) =        {            val result = new Thread            {                override def run = code            }            result.start()            result        }        val gate = new Gate        val lockHolderThread = spawn        {            this.classUnderTest.synchronized            {                // Don't let the other thread start until we've got the lock                gate.open()                // Hold the lock until interruption                try                {                    Thread.sleep(java.lang.Long.MAX_VALUE)                }                catch                {                    case ignore: InterruptedException => return;                }            }        }        val measuredNanoTime = nanoTime        {            // Don't start until the other thread is synchronized on classUnderTest            gate.await()            spawn(code).join(millisTimeout, 0)        }        val nanoTimeout = millisTimeout * 1000L * 1000L        Assert.assertEquals(            "Measured " + measuredNanoTime + " ns but timeout was " + nanoTimeout + " ns.",            threadSafe,            measuredNanoTime > nanoTimeout)        lockHolderThread.interrupt        lockHolderThread.join    }}

Now let's say we want to test a simple class:

class MySynchronized{    def synch = this.synchronized{}    def unsynch = {}}

The test looks this:

class MySynchronizedTest extends SynchronizedTestTrait{    val classUnderTest = new MySynchronized    @Test    def synch_is_synchronized    {        this.assertSynchronized        {            this.classUnderTest.synch        }    }    @Test    def unsynch_not_synchronized    {        this.assertNotSynchronized        {            this.classUnderTest.unsynch        }    }}