You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ma...@apache.org on 2011/05/11 00:59:02 UTC

svn commit: r1101674 - /commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp2/BasicDataSource.java

Author: markt
Date: Tue May 10 22:59:02 2011
New Revision: 1101674

URL: http://svn.apache.org/viewvc?rev=1101674&view=rev
Log:
With Java 1.5 onwards, double-checked locking will work is used with volatile

Modified:
    commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp2/BasicDataSource.java

Modified: commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp2/BasicDataSource.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp2/BasicDataSource.java?rev=1101674&r1=1101673&r2=1101674&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp2/BasicDataSource.java (original)
+++ commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp2/BasicDataSource.java Tue May 10 22:59:02 2011
@@ -1480,91 +1480,92 @@ public class BasicDataSource implements 
      * <p>Create (if necessary) and return the internal data source we are
      * using to manage our connections.</p>
      *
-     * <p><strong>IMPLEMENTATION NOTE</strong> - It is tempting to use the
-     * "double checked locking" idiom in an attempt to avoid synchronizing
-     * on every single call to this method.  However, this idiom fails to
-     * work correctly in the face of some optimizations that are legal for
-     * a JVM to perform.</p>
-     *
      * @throws SQLException if the object pool cannot be created.
      */
-    protected synchronized DataSource createDataSource()
+    protected DataSource createDataSource()
         throws SQLException {
         if (closed) {
             throw new SQLException("Data source is closed");
         }
 
         // Return the pool if we have already created it
+        // This is double-checked locking. This is safe since dataSource is
+        // volatile and the code is targeted at Java 5 onwards.
         if (dataSource != null) {
             return (dataSource);
         }
+        synchronized (this) {
+            if (dataSource != null) {
+                return (dataSource);
+            }
 
-        // create factory which returns raw physical connections
-        ConnectionFactory driverConnectionFactory = createConnectionFactory();
-
-        // create a pool for our connections
-        createConnectionPool();
-
-        // Set up statement pool, if desired
-        GenericKeyedObjectPoolFactory statementPoolFactory = null;
-        if (isPoolPreparedStatements()) {
-            statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
-                        -1, // unlimited maxActive (per key)
-                        GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
-                        0, // maxWait
-                        1, // maxIdle (per key)
-                        maxOpenPreparedStatements);
-        }
-
-        // Set up the poolable connection factory
-        boolean success = false;
-        try {
-            createPoolableConnectionFactory(driverConnectionFactory,
-                    statementPoolFactory, abandonedConfig);
-            success = true;
-        } catch (SQLException se) {
-            throw se;
-        } catch (RuntimeException rte) {
-            throw rte; 
-        } catch (Exception ex) {
-            throw new SQLException("Error creating connection factory", ex);
-        } finally {
-            if (!success) {
-                closeConnectionPool();
+            // create factory which returns raw physical connections
+            ConnectionFactory driverConnectionFactory = createConnectionFactory();
+    
+            // create a pool for our connections
+            createConnectionPool();
+    
+            // Set up statement pool, if desired
+            GenericKeyedObjectPoolFactory statementPoolFactory = null;
+            if (isPoolPreparedStatements()) {
+                statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
+                            -1, // unlimited maxActive (per key)
+                            GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
+                            0, // maxWait
+                            1, // maxIdle (per key)
+                            maxOpenPreparedStatements);
             }
-        }
-        
-        // Create the pooling data source to manage connections
-        success = false;
-        try {
-            createDataSourceInstance();
-            success = true;
-        } catch (SQLException se) {
-            throw se;
-        } catch (RuntimeException rte) {
-            throw rte;
-        } catch (Exception ex) {
-            throw new SQLException("Error creating datasource", ex);
-        } finally {
-            if (!success) {
+    
+            // Set up the poolable connection factory
+            boolean success = false;
+            try {
+                createPoolableConnectionFactory(driverConnectionFactory,
+                        statementPoolFactory, abandonedConfig);
+                success = true;
+            } catch (SQLException se) {
+                throw se;
+            } catch (RuntimeException rte) {
+                throw rte; 
+            } catch (Exception ex) {
+                throw new SQLException("Error creating connection factory", ex);
+            } finally {
+                if (!success) {
+                    closeConnectionPool();
+                }
+            }
+            
+            // Create the pooling data source to manage connections
+            success = false;
+            try {
+                createDataSourceInstance();
+                success = true;
+            } catch (SQLException se) {
+                throw se;
+            } catch (RuntimeException rte) {
+                throw rte;
+            } catch (Exception ex) {
+                throw new SQLException("Error creating datasource", ex);
+            } finally {
+                if (!success) {
+                    closeConnectionPool();
+                }  
+            }
+            
+            // If initialSize > 0, preload the pool
+            try {
+                for (int i = 0 ; i < initialSize ; i++) {
+                    connectionPool.addObject();
+                }
+            } catch (Exception e) {
                 closeConnectionPool();
-            }  
-        }
-        
-        // If initialSize > 0, preload the pool
-        try {
-            for (int i = 0 ; i < initialSize ; i++) {
-                connectionPool.addObject();
+                throw new SQLNestedException("Error preloading the connection pool", e);
             }
-        } catch (Exception e) {
-            closeConnectionPool();
-            throw new SQLNestedException("Error preloading the connection pool", e);
+            
+            // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor task
+            startPoolMaintenance();
+            
+            return dataSource;
         }
-        
-        // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor task
-        startPoolMaintenance();
-        
-        return dataSource;
     }
 
     /**