Java 下面的程序会崩溃吗?

Java 下面的程序会崩溃吗?,java,Java,例如,有一段Java代码,Home是一个Java类,mHome可以是任何对象中的成员: if((mHome != null) && (mHome.mName == "xxx")) { ...... } 我的问题在这里。运行条件Home.mName==“xxx”时,Home ref是否可能为空。例如,在运行语句Home!=null,线程被切换出,另一个线程被设置为null 免责声明:我没有编写java代码,但这个问题更像是一个一般的多线程问题,因此答案

例如,有一段Java代码,Home是一个Java类,mHome可以是任何对象中的成员:

if((mHome != null) && (mHome.mName == "xxx"))  
{      ......      }  
我的问题在这里。运行条件
Home.mName==“xxx”
时,Home ref是否可能为空。例如,在运行语句
Home!=null
,线程被切换出,另一个线程被设置为null

免责声明:我没有编写java代码,但这个问题更像是一个一般的多线程问题,因此答案也应该适用于java

正如您清楚地了解的,访问
Home
的不同线程可以更改任何内容,如果在
if
语句的两个部分之间发生上下文切换,则它将失败


有一种方法可以在不应用锁定/同步方法的情况下保护代码免受这种风险,即在
if
语句之前获取一个本地引用(使用一个私有变量),然后您就可以确定,如果变量不为null,那么访问它的成员是安全的。(*注:这在垃圾收集环境中是正确的,例如C++中,你可能会保留对被删除对象的引用,也会崩溃)。 您需要使代码线程安全。为此,请使用同步

下面是一个使用链接同步的示例代码

下面来自stackoverflow的链接显示了如何以不同的方式解决此问题


鉴于您给出的代码数量,很难说这段代码是否会失败。比如说,

public test(){
    Home home = ...//call the constructor of home to create an instance
    if(null!=home && home.mName=="xxx") {// bad comparison of string and bad way to access an instance variable
        //some code
    }
}
public class WrongThreadSafety {
  private static String s;
  public synchronized String setString(String s) {
    this.s = s;
  }

  public synchronized String getStringLength() {
    return s.length();
  }

}
在上述情况下,比较
home.mName==“xxx”
不会失败(即结果为空),因为
home
是该方法的局部。 但是

}

  • ->线程
    a
    已完成执行
    null=主页
  • ->
    A
    被置于睡眠状态
  • ->另一个线程
    B
    将变量
    home
    的值更改为
    null
  • ->线程
    B
    被置于睡眠状态
  • ->
    A
    恢复执行
  • ->NullPointerException
如果是后者,则应确保访问变量
home
的值的方法是
synchronized
(基本上是线程安全的)。但是理解同步有点棘手。比如说,

public test(){
    Home home = ...//call the constructor of home to create an instance
    if(null!=home && home.mName=="xxx") {// bad comparison of string and bad way to access an instance variable
        //some code
    }
}
public class WrongThreadSafety {
  private static String s;
  public synchronized String setString(String s) {
    this.s = s;
  }

  public synchronized String getStringLength() {
    return s.length();
  }

}

尽管上面的类具有同步的方法,但它实际上不是线程安全的。方法
setString
getStringLength
分别是线程安全的。也就是说,两个线程不能同时访问方法
setString
getStringLength
,但是没有任何东西可以阻止线程调用带有null的
setString
方法,同时,另一个线程调用
getStringLength
方法。

案例1:
mHome
具有局部作用域,即
mHome
是方法参数,或者
mHome
在方法内部定义

不,变量对其他线程不可见,因此在提供的语句中不能有两个不同的值


案例2:
mHome
是一个实例变量,如果
mHome
是一个实例变量,并且您有多个线程可以执行给定语句的场景,那么两个语句(即
null
检查和相等性检查)可能会看到不同的值。在这种情况下,您需要使用
synchronized
关键字来创建一个关键部分,在该部分中一次只能有一个线程进入

是该程序的本地主线程还是在多个线程之间共享?每个代码都可能崩溃。现在,您知道为什么Home.mName==“xxx”的编码不好吗?这有两个原因。(或者三个,取决于mName是什么)Java是按值传递的。如果线程共享对
Home
的引用,并且其中一个线程将对Home的引用设置为null,则其他线程可能不会真正受到影响。不过,这只是一种可能的情况。对不起,我更正了我原来的帖子。例如,mHome可以在不同的线程中访问。对于您来说,提及
mHome
是类中的实例变量还是方法中的局部变量非常重要记住java是按值传递的。HI Amit,如果我将代码更改为mHome.mName=(mHome==null)?1:2,崩溃会发生吗?user3236879:有没有发生过代码的其余部分也会对它是否会崩溃产生影响?嗨,黑豹,非常感谢你的友好回答!我完全理解你的意思。AHI黑豹,非常感谢您的友好回答!我完全理解你的意思。我认为现在没有技术问题了。但我还是有点困惑。我想,在我们做节目的时候,这种情况是很常见的。但是我们很少像你说的那样做保护,而且通常没有问题。所以…我不知道。无法解释我在我们公司的实际项目中遇到的奇怪问题。不客气……)如果您是在非线程程序中执行此操作(同样,解释此操作有点棘手,因为每个程序都有线程),则不会产生问题。大多数情况下,对象都是在本地创建的,如果是j2EE应用程序,就说每个请求。所以这不会是个问题。但如果它是一个共享资源,那么它就是。例如,同一个用户同时通过两个不同的浏览器登录应用程序,并在浏览器
a
中添加一个产品,然后将其从浏览器
B
中删除,如果处理不当,则会造成混乱。