如何使getFoo()和getBar()线程安全?这样同时一个线程可以调用getFoo()而另一个线程可以调用getBar()...即我不想在类级锁定上同步..
private static Foo foo;
private static Bar bar;
private static void initBar() {
bar = SomeOtherClass.getBarVal();
}
private static void initFoo() {
foo = SomeOtherClass.getFooVal();
}
public static Foo getFoo() {
if (foo == null) {
initFoo();
}
return foo;
}
public static Bar getBar() {
if (bar == null) {
initBar();
}
return bar;
}
答案 0 :(得分:3)
您不需要锁定getFoo()
和getBar()
,只需要锁定init块:
private static volatile Foo foo;
private static volatile Bar bar;
private static final Object fooLock = new Object();
private static final Object barLock = new Object();
private static void initBar() {
bar = SomeOtherClass.getBarVal();
}
private static void initFoo() {
foo = SomeOtherClass.getFooVal();
}
public static Foo getFoo() {
if (foo == null) {
synchronized (fooLock) {
if (foo == null) {
initFoo();
}
}
}
return foo;
}
public static Foo getBar() {
if (bar == null) {
synchronized (barLock) {
if (bar == null) {
initBar();
}
}
}
return foo;
}
答案 1 :(得分:1)
private static Foo foo;
private static Bar bar;
private static final Object fooLock = new Object();
private static final Object barLock = new Object();
private static void initBar() {
bar = SomeOtherClass.getBarVal();
}
private static void initFoo() {
foo = SomeOtherClass.getFooVal();
}
public static Foo getFoo() {
synchronized(fooLock){
if (foo == null) {
initFoo();
}
}
return foo;
}
public static Bar getBar() {
synchronized(barLock){
if (bar == null) {
initBar();
}
}
return bar;
}
使用两把锁。
修改强>
如果您使用的是单身模式,我建议您继续阅读:
答案 2 :(得分:0)
public static Foo getBar() {
return BarInstanceHolder.barInstance;
}
public static Foo getFoo() {
return FooInstanceHolder.fooInstance;
}
private static final class BarInstanceHolder {
static final Bar barInstance = SomeOtherClass.getBarVal();
}
private static final class FooInstanceHolder {
static final Foo fooInstance = SomeOtherClass.getFooVal();
}
答案 3 :(得分:0)
private static final class FooInstanceHolder {
static final Foo fooInstance = SomeOtherClass.getFooVal();
}
当类FooInstanceHolder加载到内存中时初始化foo。在完全加载类之前,可以调用方法。