Java 函数是否线程安全?

Java 函数是否线程安全?,java,Java,我正在读“实践中的Java并发”。我们的函数如下所示: public class LazyInitRace { private ExpensiveObject instance = null; public ExpensiveObject getInstance() { if (instance == null) instance = new ExpensiveObject(); return instance; }

我正在读“实践中的Java并发”。我们的函数如下所示:

public class LazyInitRace {
   private ExpensiveObject instance = null;
   public ExpensiveObject getInstance() { 
       if (instance == null)
          instance = new ExpensiveObject(); 
       return instance;
   } 
 }
作者说,这不是线程安全的。然而我认为,“实例”变量不是静态变量,因此是线程安全的。
我认为只有当同一个类实例被两个线程访问时,它才会变得线程不安全。我需要知道我所想的是正确的还是错误的?

不管变量是非静态的还是静态的。其目的是为每个实例创建一个实例,并且只创建一次


此处未完全填充-当两个并行线程进入此方法时,变量可能会显示为
null
,两者都将创建新实例。您需要使用
synchronized

包装代码或方法,不管变量是非
静态的
还是
静态的
。其目的是为每个实例创建一个实例,并且只创建一次

此处未完全填充-当两个并行线程进入此方法时,变量可能会显示为
null
,两者都将创建新实例。您需要使用
synchronized

包装代码或方法。线程安全是一种适用于多线程程序上下文的计算机编程概念。如果一段代码只以保证多个线程同时安全执行的方式操作共享数据结构,那么它就是线程安全的

class Singleton {

private volatile static Singleton _instance;

private Singleton() {
    // preventing Singleton object instantiation from outside 
}

/* 
 * 1st version: creates multiple instance if two thread access 
 * this method simultaneously 
 */

public static Singleton getInstance() {
    if (_instance == null) {
        _instance = new Singleton();
    }
    return _instance;
} 

/* 
 * 2nd version : this definitely thread-safe and only 
 *creates one instance of Singleton on concurrent environment 
 * but unnecessarily expensive due to cost of synchronization 
 * at every call. 
 */


public static synchronized Singleton getInstanceTS() {
    if (_instance == null) {
        _instance = new Singleton();
    }
    return _instance;
}
/* 
 * 3rd version : An implementation of double checked locking of Singleton. 
 * Intention is to minimize cost of synchronization and improve performance, 
 * by only locking critical section of code, the code which creates instance of Singleton class. 
 * By the way this is still broken, if we don't make _instance volatile, as another thread can 
 * see a half initialized instance of Singleton. 
 */

public static Singleton getInstanceDC() {
    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                _instance = new Singleton();
            }
        }
    }
    return _instance;
}
}线程安全是一种适用于多线程程序的计算机编程概念。如果一段代码只以保证多个线程同时安全执行的方式操作共享数据结构,那么它就是线程安全的

class Singleton {

private volatile static Singleton _instance;

private Singleton() {
    // preventing Singleton object instantiation from outside 
}

/* 
 * 1st version: creates multiple instance if two thread access 
 * this method simultaneously 
 */

public static Singleton getInstance() {
    if (_instance == null) {
        _instance = new Singleton();
    }
    return _instance;
} 

/* 
 * 2nd version : this definitely thread-safe and only 
 *creates one instance of Singleton on concurrent environment 
 * but unnecessarily expensive due to cost of synchronization 
 * at every call. 
 */


public static synchronized Singleton getInstanceTS() {
    if (_instance == null) {
        _instance = new Singleton();
    }
    return _instance;
}
/* 
 * 3rd version : An implementation of double checked locking of Singleton. 
 * Intention is to minimize cost of synchronization and improve performance, 
 * by only locking critical section of code, the code which creates instance of Singleton class. 
 * By the way this is still broken, if we don't make _instance volatile, as another thread can 
 * see a half initialized instance of Singleton. 
 */

public static Singleton getInstanceDC() {
    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                _instance = new Singleton();
            }
        }
    }
    return _instance;
}

}当我们说一个程序是线程安全的时,它意味着该程序的所有线程对程序中的数据值都有一个一致的视图。这里有一个简单的例子。假设
something
是一个
ExpensiveObject
,它已由
getInstance
方法初始化,并且对程序的所有线程都可见。另外,
classObject
Class
类型的对象。现在考虑下面的代码片段,由某个线程运行:

if(something != null)
  classObject = something.getClass();

看起来像是一个
NullPointerException
是不可能的,对吗?不是。介于
if(something!=null)
classObject=something.getClass()之间
另一个线程可以将
something
的值更改为
null
。这个程序不是线程安全的,因为对
某物的读写不是同步的,这确保了所有线程对
某物的值都有一个一致的视图。

当我们说一个程序是线程安全的时,这意味着该程序的所有线程都有一个一致的视图程序中数据的值。这里有一个简单的例子。假设
something
是一个
ExpensiveObject
,它已由
getInstance
方法初始化,并且对程序的所有线程都可见。另外,
classObject
Class
类型的对象。现在考虑下面的代码片段,由某个线程运行:

if(something != null)
  classObject = something.getClass();

看起来像是一个
NullPointerException
是不可能的,对吗?不是。介于
if(something!=null)
classObject=something.getClass()之间
另一个线程可以将
something
的值更改为
null
。这个程序不是线程安全的,因为对
某物的读写不是同步的,这确保所有线程对
某物的值都有一致的看法。

如果它们不是静态的,那么你需要新建一个对象,然后使用它的getInstance,那么单例模式将是meaningless@FireSun:我不认为这是在尝试单例操作,只是尝试在每个实例中只实例化一次
ExpensiveObject
,并放在一个位置(
getInstance
)。对于该方法来说,grated
getInstance
是一个相当不可靠的名称。如果它们不是静态的,那么您需要新建一个对象,然后使用它的getInstance,然后使用singleton模式meaningless@FireSun:我不认为这是在尝试单例,只是尝试在一个实例中实例化
ExpensiveObject
一次(
getInstance
)。对于该方法来说,
getInstance
是一个相当不可靠的名称。您的示例仅与问题有远程关联。您的示例仅与问题有远程关联。