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)
谢谢
不它不是。
您引用的这句话意味着静态方法不是特定于对象的,并且由于局部变量保存在线程环境中,因此只能从线程本身的本地执行中访问它。但是在静态方法中,您可以访问静态字段或由多个线程共享的对象,在这种情况下,您处理的不是局部变量,而是多个对象之间共享的内容。
换句话说,由于执行是线程安全的,因此对对象字段的访问由有权访问该对象的所有线程共享。在这种情况下,您会遇到并发问题,必须使用关键字来处理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)
}
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)