title: How to synchronize two methods in a singleton pattern
body: <p>I have created a database object according to the singleton pattern. The database object contains 2 methods: <code>connect()</code> and <code>update()</code>. </p>
  
  <p>The update should run multithreaded, meaning that I cannot put <code>synchronized</code> in the <code>update</code> method signature (I want users to access it simultaneously not one at a time).</p>
  
  <p>My problem is that I want to make sure that 2 scenarios according to this flows:</p>
  
  <ol>
  <li><p>A thread 1 (user1) is the first to create an instance of the DB and thread 2 (user2) is calling the <code>connect()</code> and <code>update()</code> method to this DB - should not give <code>NullPointerException</code> even if by the time that user2 is doing the <code>update()</code> the connect from user1 is not done.</p></li>
  <li><p><code>update()</code> should not include <code>synchronized</code> (because of the reason I mentioned above).
  Thanks for all the helpers!</p></li>
  </ol>
  
  <p>SingeltonDB </p>
  
  <pre><code>import java.util.concurrent.locks.Lock;
  import java.util.concurrent.locks.ReentrantLock;
  
      public class SingeltonDB {
          private static DBconnImpl db = null;
          private static SingeltonDB singalDb = null;
            Lock dbLock;
  
          private SingeltonDB(String username, String password) {
              db = new DBconnImpl();
          }
  
          public static boolean isOpen() {
              return (db != null);
          }
  
          public synchronized static SingeltonDB getInstance(String username,
                  String password) throws Exception {
  
              if (db != null) {
                  throw (new Exception("The database is  open"));
              } else {
                  System.out.println("The database is now open");
                  singalDb = new SingeltonDB(username, password);
              }
              db.connect(username, password);
              System.out.println("The database was connected");
  
              return singalDb;
          }
  
          public synchronized static SingeltonDB getInstance() throws Exception {
              if (db == null) {
                  throw (new Exception("The database is not open"));
              }
  
              return singalDb;
          }
  
          public void create(String tableName) throws Exception {
              dbLock = new ReentrantLock();
              dbLock.lock();
              db.create(tableName);
              dbLock.unlock();
          }
  
          public  User query(String tableName, int rowID) throws Exception {
              if (db == null) {
                  System.out.println("Error: the database is not open");
                  return null;
              }
              return (db.query(tableName, rowID));
          }
  
          public  void update(String tableName, User user) throws Exception {
              if (db == null) {
                  System.out.println("Error: the database is not open");
                  return;
              }
              db.update(tableName, user);
          }
  
      }
  </code></pre>
  
  <p>Main </p>
  
  <pre><code>public class Main {
      public static void main(String[] args) throws Exception {
  
          Creator cr= new Creator(new UserContorller());
          Thread t1 = new Thread(cr);
          t1.start();
          Producer pr = new Producer(new UserContorller());
          Thread t2 = new Thread(pr);
          t2.start();
  
          /*
           * Consumer cn = new Consumer(new UserContorller()); Thread t2 = new
           * Thread(cn); t2.start();
           */
      }
  }
  
  class Creator implements Runnable {
      UserContorller uc;
  
      public Creator(UserContorller uc) {
          this.uc = uc;
      }
  
      @Override
      public void run() {
          try {
              uc = new UserContorller("MyAccount", "123");
              uc.createTable("table1");
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  }
  
  class Producer implements Runnable {
      UserContorller uc;
  
      public Producer(UserContorller uc) {
          this.uc = uc;
      }
  
      @Override
      public void run() {
          for (int i = 0; i &lt; 100; i++) {
              try {
                  uc.saveUser("table1", i, "User", i);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
  
  }
  
  class Consumer implements Runnable {
      UserContorller uc;
  
      public Consumer(UserContorller uc) {
          this.uc = uc;
      }
  
      @Override
      public void run() {
          for (int i = 0; i &lt; 100; i++) {
              try {
                  System.out.println(uc.getUser("table1", i));
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
  
  }
  </code></pre>