Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: rearranged text

...

This noncompliant code example begins initializing the class Lazy. The code in the static block is responsible for initialization, and starts a background thread. The background thread attempts to initialize a database connection but needs to wait until initialization of all members of the Lazy class, including dbConnection, has finished.

Code Block
bgColor#FFcccc
public final class Lazy {
  private static Connection dbConnection;
	  
  static {
    Thread dbInitializerThread = new Thread(new Runnable() {
      public void run() {
        // Initialize the database connection
        try {
          dbConnection = DriverManager.getConnection("connectionstring");	 
        } catch (SQLException e) {
          dbConnection = null;	
	}
      }
    });
	    
    dbInitializerThread.start();
    try {
      dbInitializerThread.join();
    } catch(InterruptedException ie) {
      throw new AssertionError(ie);
    }
    // Other initialization   
  }
	  
  public static Connection getConnection() {
    if(dbConnection == null) {
      throw new IllegalStateException("Error initializing connection");  
    }
    return dbConnection;
  }
	  
  public static void main(String[] args) {
    // ...
    Connection connection = Lazy.getConnection();
  }
}

...

Wiki Markup
Recall that statically-initialized fields are guaranteed to be fully constructed before becoming visible to other threads (see [CON26-J. Do not publish partially initialized objects] for more information). Consequently, the background thread must wait for the foreground thread to finish initialization before it can proceed. However, the {{Lazy}} class's main thread invokes the {{join()}} method which waits for the background thread to finish. This interdependency causes a class initialization cycle that results in a deadlock situation. \[[Bloch 05b|AA. Java References#Bloch 05b]\] 

...