我有一个这样的课程:
public class Utils {
public static void doSomething() {
// doSomething code
}
public static void doSomethingElse() {
// doSomethingElse code
}
}
我希望这两个方法同步但不能彼此同步,即没有两个线程可以同时处理doSomething()方法,没有两个线程可以同时处理doSomethingElse()但是它可以一个处理doSomething()方法的线程,另一个处理doSomethingElse()方法。
我已经实现了这样的事情:
public class Utils {
private static final String DO_SOMETHING_LOCK = "DO_SOMETHING_LOCK";
private static final String DO_SOMETHING_ELSE_LOCK = "DO_SOMETHING_ELSE_LOCK";
public static void doSomething() {
synchronized(DO_SOMETHING_LOCK) {
// doSomething code
}
}
public static void doSomethingElse() {
synchronized(DO_SOMETHING_ELSE_LOCK) {
// doSomethingElse code
}
}
我看到Scott Stanchfield的回应采用了类似的方法:
How do synchronized static methods work in Java?
但这是最好的方法吗?对我来说似乎有点笨拙,创造了两个对象,只是用于锁定 - 有更好的方法吗?
答案 0 :(得分:5)
使用字符串不是一个好主意,因为相同的字符串可能出现在其他地方,它将是同一个对象,您可以获得依赖项,而不是它们。只是做
private static final Object DO_SOMETHING_LOCK = new Object();
其余的都没问题。
答案 1 :(得分:1)
是的,这是最简单的方法。虽然,你锁定的对象不一定是特别的。你可以让它们成为没有设置值的整数。
答案 2 :(得分:1)
锁定实习String
是一个错误。如果您运行FindBugs,我相信它会为您指出这一点。为锁定创建对象的新实例 - new Object()
或new String("Something informative")
。要在堆栈跟踪锁定时查看有用的内容,请使用该作业的自定义类。
private final Object lock = new Object() { };
或
private static final class MyLock { }
private final Object lock = new MyLock();
事实上,创建私有内部对象(对象非常小 - 做数学)通常比通过公共接口公开锁更好。
答案 3 :(得分:-2)
您的解决方案似乎是正确的。我经常看到/使用Object的实例作为锁(而不是字符串),如:
public class Utils {
private static final Object[] lock = new Object[] { new Object(), new Object() };
public static void doSomething() {
synchronized(lock[0]) {
// doSomething code
}
}
...
}
您尝试解决的问题与ThreadLocal类用例有关。