2012-01-31 112 views
9

有关于这个问题的其他问题,但我正在努力思考如何接近单元测试是这样的:如何编写单元测试,测试并发不变

public class Semaphore extends Lock { 
     private AtomicInteger semaphore = new AtomicInteger(0); 
     public synchronized boolean available() { 
       return semaphore.intValue() == 0; 
     } 
     public synchronized void acquire() { 
      semaphore.incrementAndGet(); 

     } 
     public synchronized void release() { 
      semaphore.decrementAndGet(); 
     } 
    } 

这是我的朴素的锁定机制(只是为了学习目的)。我将如何测试这个线程的安全性?我知道单元测试并发代码没有保证,但我怎么会写一个单元测试,ATTEMPTS测试这个锁定机制中固有的明显不变量?

+0

静态分析是不是问题? – UmNyobe 2012-01-31 22:29:14

+0

不,不完全没有问题。但我更想知道什么样的单元测试甚至可以像这样的东西......再次承认,在并发性方面没有任何单元测试能够保证任何东西。 – LuxuryMode 2012-01-31 22:31:45

+2

通常,你会使用各种技巧 - 运行一堆随机调度的线程,释放一个线程中的锁而其他两个线程正在旋转,等等。这是一门艺术。 – 2012-01-31 23:05:28

回答

5

我想我会回答我自己的问题,因为我做了一些研究。有一个很好的框架叫做MultithreadedTC。它允许你设置的测试,像这样:

public class SafeSemaphoreTest extends MultithreadedTestCase { 

    private SafeSemaphore semaphore; 
    AtomicInteger ai = new AtomicInteger(0); 

    @Override 
    public void initialize() { 
     semaphore = new SafeSemaphore(); 
    } 


    public void thread1() throws InterruptedException { 

     assertTick(0); 

     semaphore.acquire(); 
     waitForTick(2); 
     assertTick(2); 

     semaphore.acquire(); 
     assertEquals(semaphore.getValue(), 2); 
     assertEquals(semaphore.getValue()==3, false); 
     semaphore.release(); 
     semaphore.release(); 

    } 

    public void thread2() throws InterruptedException { 
     waitForTick(1); 
     assertTick(1); 
     assertEquals(semaphore.available(), false); 
     waitForTick(3); 
     assertTick(3); 
     assertEquals(semaphore.available(), true); 

    } 

} 

其中waitForTick(INT)调用使当前线程块,直到达到刻度。甚至有一些发展使得这个更好的JUnit集成更现代一点: http://janvanbesien.blogspot.com/2009/06/modernizing-multithreadedtc-junit-4.html