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

前端 未结 4 411
野趣味
野趣味 2020-12-10 02:29

I have several classes that implement some interface. The interface has a contract, that some methods should be synchronized, and some should not, and I want to verify that

4条回答
  •  醉梦人生
    2020-12-10 03:30

    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.

提交回复
热议问题