Reputation: 61
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
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
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