给定一个具有静态方法的类&非静态实例方法 如何确保在任何时间点只有其中一个方法被调用?我们如何确保在任何时候只有一个类的静态方法和非静态方法被调用?
例子: ------
public class DoMath{
public static int getSum(){
//Sum
}
public int getSub(){
//Subtract
}
}
现在,您需要确保在任何一个时间点,只有上述两种方法被调用。
给定一个具有静态方法的类&非静态实例方法 如何确保在任何时间点只有其中一个方法被调用?我们如何确保在任何时候只有一个类的静态方法和非静态方法被调用?
例子: ------
public class DoMath{
public static int getSum(){
//Sum
}
public int getSub(){
//Subtract
}
}
现在,您需要确保在任何一个时间点,只有上述两种方法被调用。
这应该这样做。
public class DoMath{
public static synchronized int getSum(){
//Sum
}
public int getSub(){
synchronized(DoMath.class) {
//Subtract
}
}
}
说明:一个static synchronized
方法隐含地将同步声明的方法的类的Class
对象上。
最佳做法是使用私人锁具。这可以防止从课堂外锁定代码。这在下面的例子中得到了证明。请注意输出中的执行顺序 - 在可公开访问的类监视器发布之前,DoMathExposed#getSum()无法返回。另一方面,DoMathEncapsulated#getSum()会立即返回,因为它是在一个私有对象上同步的,因此保持公共类监视器不起作用。
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;
}
}
}
锁对象的优点是什么? 我相信你试图做的是同步两个方法使用类级锁? –
使用同步方法或同步DoMath对象本身可以将锁持有者暴露给外部世界。这意味着别人可能会获得锁并阻止您的代码。使用私有锁持有者被认为是最佳实践,因为它在对象中封装了锁定行为 - 在这种情况下是DoMath。 – dimplex
你能否举个例子说明我的锁具是否暴露在外部世界,并且它被滥用了。任何小例子或资源都将有助于理解它,对其他人来说也是有益的,他们可能正在寻找现在/将来。 –
但是我们可以对实例方法做类级锁吗? –
是的。这就是我执行'getSub'的过程。 –