java-静态方法隐式线程安全吗?

Jav*_*ser 5 java singleton multithreading synchronized

我的java 静态方法之一可以由多个线程访问。是否需要通过synced关键字显式地同步该方法?

有时我读了一本书说

静态方法是隐式线程安全的,因为该方法不是特定于对象的

众所周知的示例是Singleton实现。在哪个getInstance()中是静态的,是否还需要将其标记为已同步?

 public synchronized static Logger getInstance() {
         if( instance == null ){
             instance = new Logger();
         }

         return instance;
     }
Run Code Online (Sandbox Code Playgroud)

谢谢

Rob*_*ato 5

不它不是。

您引用的这句话意味着静态方法不是特定于对象的,并且由于局部变量保存在线程环境中,因此只能从线程本身的本地执行中访问它。但是在静态方法中,您可以访问静态字段或由多个线程共享的对象,在这种情况下,您处理的不是局部变量,而是多个对象之间共享的内容。

换句话说,由于执行是线程安全的,因此对对象字段的访问由有权访问该对象的所有线程共享。在这种情况下,您会遇到并发问题,必须使用关键字来处理synchronized。使用synchronized 关键字,您每次只能从一个线程访问一条语句。

class MyObject{
 static MyType mySharedObject; //if you access this in static methos you are not safe until you sync the access

public static void myMethod(){
   int localVar; //that is safely accessed
   mySharedObject.setSomething(pippo); //that is not safe in multi thread environment.

}
Run Code Online (Sandbox Code Playgroud)

}


dav*_*xxx 5

static 修饰符和线程安全是两个不同的问题。

只有当您没有任何竞争条件时,您才处于事实上的头部安全案例中。
方法没有竞争条件意味着:

  • 对方法的访问要么由单个线程完成

  • 通过并发线程但仅用于读取访问

这两件事与方法是否为静态的事实零关系。

例如在这段代码中:

public static Logger getInstance() {
     if( instance == null ){
         instance = new Logger();
     }

     return instance;
}
Run Code Online (Sandbox Code Playgroud)

如果应用程序是单线程的,它实际上是线程安全的。
但如果它是由线程并发访问的,则情况并非如此,因为该方法不仅仅进行读取访问
在这种情况下,您需要同步对方法的访问。


作为旁注,Bill Pugh 惯用单例没有使用同步方法来实现单例。
您确实可以通过利用 JVM 在加载类时完成的静态初始化来实现它:

public class SingletonBillPughWithEagerCreation {

    // executed as soon as the SingletonBillPughWithEagerCreation class is loaded by the classLoader
    private static SingletonBillPughWithEagerCreation instance = new SingletonBillPughWithEagerCreation();

    private SingletonBillPughWithEagerCreation() {
    }

    public static SingletonBillPughWithEagerCreation getInstance() {
       return instance;
    }
}
Run Code Online (Sandbox Code Playgroud)