以下程序会崩溃吗?

时间:2015-05-22 06:08:40

标签: java

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

if((mHome != null) && (mHome.mName == "xxx"))  
{      ......      }  

我的问题在这里。运行条件Home.mName == "xxx"时,Home ref是否可能为null。例如,在运行语句Home != null之后,线程将被切换,另一个线程将Home置为null。

4 个答案:

答案 0 :(得分:1)

  

块引用

根据您提供的代码量,很难说这件作品是否会失败。例如,

home.mName=="xxx"

在上面的例子中,比较home不会失败(导致为null),因为public test() { Home home = this.getHome(); // assuming home is an instance variable if(null!=home && home.mName=="xxx") {// bad comparison of string and bad way to access an instance variable //some code } } 是方法的本地。 但

A

}

时有机会
  • - >线程null!=home已完成执行A
  • - > B被置于睡眠
  • - >另一个帖子home将变量null的值更改为B
  • - >线程A被置于睡眠
  • - > home 恢复执行
  • - >的的NullPointerException

如果后者是这种情况,那么你应该确保访问变量synchronized的值的方法是public class WrongThreadSafety { private String s; public synchronized String setString(String s) { this.s = s; } public synchronized String getStringLength() { return s.length(); } } (基本上是线程安全的)。但是理解同步有点棘手。例如,

synchronized

虽然上面的类的方法是setString,但它确实不是线程安全的。方法getStringLengthsetString是单独的线程安全的。这是两个线程无法同时访问方法getStringLengthsetString,但没有任何东西阻止线程使用null调用getStringLength方法,同时另一个线程调用 for (card = top; card <= top + 4; ++card) 方法。

答案 1 :(得分:0)

  

免责声明:我不编码java,但问题更多的是一般的多线程问题,所以答案也应该适用于java。

正如您清楚地了解的那样,可以访问-- MySQL Workbench Forward Engineering SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES'; -- ----------------------------------------------------- -- Schema JarvisDB -- ----------------------------------------------------- -- ----------------------------------------------------- -- Schema JarvisDB -- ----------------------------------------------------- CREATE SCHEMA IF NOT EXISTS `JarvisDB` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ; USE `JarvisDB` ; -- ----------------------------------------------------- -- Table `JarvisDB`.`jarvisFixtures` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `JarvisDB`.`jarvisFixtures` ( Id INT NOT NULL, Gender VARCHAR(10) NOT NULL, Section VARCHAR(10) NOT NULL, Team1 VARCHAR(10) NOT NULL, Team2 VARCHAR(10) NOT NULL, FixtureD DATETIME NOT NULL, FixtureT VARCHAR(10) NOT NULL, Venue VARCHAR(20) NOT NULL, Court VARCHAR(5) NOT NULL, PRIMARY KEY (Id), UNIQUE INDEX `Id_UNIQUE` (Id ASC)) ENGINE = InnoDB; SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; -- ----------------------------------------------------- -- Data for table `JarvisDB`.`jarvisFixtures` -- ----------------------------------------------------- START TRANSACTION; USE `JarvisDB`; INSERT INTO `JarvisDB`.`jarvisFixtures` (Id, Gender, Section, Team1, Team2, FixtureD, FixtureT, Venue, Court) VALUES (1, 'Men', 'A', 'NW', 'Gauteng', '15 July 2015', '09:00', 'Potch CC', '3'); INSERT INTO `JarvisDB`.`jarvisFixtures` (Id, Gender, Section, Team1, Team2, FixtureD, FixtureT, Venue, Court) VALUES (2, 'Men', 'A', 'NW', 'WP', '15 July 2015', '14:00', 'Potch CC', '2'); INSERT INTO `JarvisDB`.`jarvisFixtures` (Id, Gender, Section, Team1, Team2, FixtureD, FixtureT, Venue, Court) VALUES (3, 'Men', 'A', 'Northerns', 'Gauteng', '15 July 2015', '09:00', 'Potch CC', '1'); INSERT INTO `JarvisDB`.`jarvisFixtures` (Id, Gender, Section, Team1, Team2, FixtureD, FixtureT, Venue, Court) VALUES (4, 'Men', 'A', 'KZN', 'WP', '16 July 2015', '09:00', 'Defence', '5'); INSERT INTO `JarvisDB`.`jarvisFixtures` (Id, Gender, Section, Team1, Team2, FixtureD, FixtureT, Venue, Court) VALUES (5, 'Men', 'A', 'EP', 'NW', '16 July 2015', '12:00', 'Defence', '4'); INSERT INTO `JarvisDB`.`jarvisFixtures` (Id, Gender, Section, Team1, Team2, FixtureD, FixtureT, Venue, Court) VALUES (6, 'Men', 'A', 'WP', 'Northerns', '16 July 2015', '14:00', 'Puk', '5'); COMMIT; 的其他线程可以更改任何内容,并且如果上下文切换发生在Home语句的两个部分之间,则它将失败。

有一种方法可以保护您的代码免受此风险而不应用锁定/同步方法,即通过在if语句之前获取本地引用(使用私有变量)然后您确定如果变量不为null,访问它的成员是安全的。 (*注意:这仅适用于垃圾收集环境,例如在C ++中,您可能最终会持有对已删除对象的引用,并且也会崩溃)。

答案 2 :(得分:0)

您问题的直接答案是==&gt;是的,这是可能的。

您需要使代码线程安全。为此使用同步

以下是使用链接http://www.jguru.com/faq/view.jsp?EID=124425

进行同步的示例代码
package com.jgk.patterns.singleton;

public class JGKSingleton {

  /* Here is the instance of the Singleton */
  private static JGKSingleton instance_;

  /* Need the following object to synchronize */
  /* a block */
  private static Object syncObject_;

  /* Prevent direct access to the constructor
  private JGKSingleton() {
    super();
  }


  public static JGKSingleton getInstance() {

    /* in a non-thread-safe version of a Singleton   */
    /* the following line could be executed, and the */ 
    /* thread could be immediately swapped out */
    if (instance_ == null) {

      synchronized(syncObject_) {

        if (instance_ == null) {
           instance_ = new JGKSingleton();
        }

      }

    }
    return instance_;
  }
}

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

Java null check

答案 3 :(得分:0)

案例1:mHome有一个局部范围,即mHome是方法参数,或mHome在方法中定义

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

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