0

如何使 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;
}
4

4 回答 4

3

您不需要锁定getFoo()and 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;
}
于 2013-10-13T07:23:35.077 回答
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;
}

使用两把锁。

编辑

如果您使用的是单例模式,我建议您继续阅读:

单例

于 2013-10-13T07:27:46.637 回答
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();   
  }
于 2013-10-13T07:44:37.957 回答
0
  private static final class FooInstanceHolder {
static final Foo fooInstance = SomeOtherClass.getFooVal();   

}

类 FooInstanceHolder 加载到内存时初始化 foo。在类完全加载之前不能调用任何方法。

于 2013-10-13T09:50:01.500 回答