Mayank Mukherjee
Mayank Mukherjee

Reputation: 61

How can we make sure that at any point of time only one of a static method & a non-static method of a class gets called?

Given a class having a static method & a non-static instance method, How will you make sure that at any point of time only one of these methods gets called ?

Example: ——————

public class DoMath{


public static int getSum(){
//Sum
}

public int getSub(){
//Subtract
}

}

Now you need to make sure that at any one point of time , only either of these methods gets called.

Upvotes: 1

Views: 64

Answers (2)

dimplex
dimplex

Reputation: 494

The best practice is to use a private lock holder. This prevents locking your code from outside the class. This is demonstrated in the example below. Note the order of execution in the output - DoMathExposed#getSum() cannot return before the publicly accessible class monitor is released. On the other hand, DoMathEncapsulated#getSum() returns immediately since it is synchronized on a private object, so holding the public class monitor has no effect.

import java.util.concurrent.CountDownLatch;

public class DoMath {

    public static void main(String[] args) throws InterruptedException {

        System.out.println("\nTesting DoMathExposed.class\n");
        DoMathExposed.x = 3;
        DoMathExposed.y = 4;
        obtainMonitorOf(DoMathExposed.class);
        System.out.println("Invoked DoMathExposed#getSum()");
        System.out.println("DoMathExposed#getSum() returned: " + DoMathExposed.getSum());

        System.out.println("\nTesting DoMathEncapsulated.class\n");
        DoMathEncapsulated.x = 1;
        DoMathEncapsulated.y = 2;
        obtainMonitorOf(DoMathEncapsulated.class);
        System.out.println("Invoked DoMathEncapsulated#getSum()");
        System.out.println("DoMathEncapsulated#getSum() returned: " + DoMathEncapsulated.getSum());
    }

    private static void obtainMonitorOf(final Class cls) throws InterruptedException {
        final CountDownLatch latch = new CountDownLatch(1);
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(cls) {
                    System.out.println(cls.getName() + ".class MONITOR held for 10 seconds");
                    latch.countDown();
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                    }
                }
                System.out.println(cls.getName() + ".class MONITOR released");
            }
        }).start();
        latch.await();
    }
}


class DoMathEncapsulated {

    private static final Object lock = new Object();

    protected static int x;
    protected static int y;

    public static int getSum() {
        synchronized(lock) {
            return x + y;
        }
    }

    public int getSub() {
        synchronized(lock) {
            return x - y;
        }
    }
}

class DoMathExposed {

    protected static int x;
    protected static int y;

    public static synchronized int getSum() {
        return x + y;
    }

    public int getSub() {
        synchronized(DoMathExposed.class) {
            return x - y;
        }
    }
}

Upvotes: 1

Stephen C
Stephen C

Reputation: 718986

This should do it.

public class DoMath{
    public static synchronized int getSum(){
        //Sum
    }

    public int getSub(){
        synchronized(DoMath.class) {
            //Subtract
        }
    }
}

Explanation: a static synchronized method implicitly synchronizes on the Class object of the class that declared the method.

Upvotes: 1

Related Questions