测试Java方法是否同步的好方法是什么?

Cra*_*lin 16 java multithreading synchronization unit-testing thread-safety

我有几个实现一些接口的类.接口有一个契约,有些方法应该同步,有些不应该,我想通过单元测试来验证所有实现的合同.这些方法应使用synchronized关键字或锁定this- 非常类似于synchronizedCollection()包装器.这意味着我应该能够在外部观察它.

要继续的例子Collections.synchronizedCollection() ,如果我有一个线程调用迭代器(),我应该仍然能够进入象add()与另一个线程方法,因为迭代器()不应该做任何锁定.另一方面,我应该能够在外部同步集合,并在add()上看到另一个线程阻塞.

有没有一种方法可以测试方法是否在JUnit测试中同步?我想避免长时间的睡眠陈述.

pol*_*nts 5

如果你只是想检查的方法有synchronized修正,除了明显的(看源代码/ Javadoc中),你也可以使用反射.

Modifier.isSynchronized(method.getModifiers())
Run Code Online (Sandbox Code Playgroud)

测试方法是否保证在所有并发方案中正确同步的更一般的问题可能是一个不可判定的问题.

  • 如果它在内部使用“同步”块怎么办? (2认同)
  • 嗯,我看到问题描述已被编辑,现在添加更多新信息...... (2认同)

Cra*_*lin 4

非常感谢 Zwei steinen 写下了我使用的方法。我解决的示例代码中存在一些问题,因此我认为值得在这里发布我的发现。

  • 对 join() 的调用需要毫秒数,而不是纳秒数。
  • 这两个线程必须协调,否则尝试线程可以在锁线程获取锁之前启动并完成所有操作。
  • 在我们记录开始时间之前,不应启动尝试线程。否则,该线程会获得足够的领先优势,导致记录的时间可能略小于超时,从而导致虚假故障。

以下是作为 Scala 特征的同步测试代码:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

现在假设我们要测试一个简单的类:

class MySynchronized
{
    def synch = this.synchronized{}
    def unsynch = {}
}
Run Code Online (Sandbox Code Playgroud)

测试看起来是这样的:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)