如何在不使用类级别锁定的情况下同步两个静态方法

时间:2013-10-13 07:19:03

标签: java multithreading thread-safety

如何使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 个答案:

答案 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;
}

使用两把锁。

修改

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

simply singleton

答案 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。在完全加载类之前,可以调用方法。