diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index e1b447c..c9cf694 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -908,23 +908,29 @@ function drupal_get_filename($type, $name, $filename = NULL) {
  * configuration file.
  */
 function variable_initialize($conf = array()) {
-  // NOTE: caching the variables improves performance by 20% when serving
-  // cached pages.
-  if ($cached = cache_get('variables', 'cache_bootstrap')) {
-    $variables = $cached->data;
-  }
-  else {
-    // Cache miss. Avoid a stampede.
-    $name = 'variable_init';
-    if (!lock_acquire($name, 1)) {
-      // Another request is building the variable cache.
-      // Wait, then re-run this function.
-      lock_wait($name);
-      return variable_initialize($conf);
+  $retry_limit = isset($conf['variable_initialize_retry_limit']) ? $conf['variable_initialize_retry_limit'] : 5;
+
+  $name = 'variable_init';
+  $tries = 0;
+  $lock_acquired = FALSE;
+  do {
+    $tries++;
+    if ($cache = cache_get('variables', 'cache_bootstrap')) {
+      $variables = $cache->data;
     }
     else {
-      // Proceed with variable rebuild.
-      $variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed());
+      $lock_acquired = lock_acquire($name, 5);
+      if (!$lock_acquired) {
+        lock_wait($name, 0.2);
+      }
+    }
+  }
+  while (!$cache && !$lock_acquired && ($tries < $retry_limit));
+
+  if (!$cache) {
+    $variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed());
+    // Only write the cache back if we succeeded in acquiring the lock.
+    if ($lock_acquired) {
       cache_set('variables', $variables, 'cache_bootstrap');
       lock_release($name);
     }
diff --git a/includes/lock.inc b/includes/lock.inc
index 7dd8db3..25b4443 100644
--- a/includes/lock.inc
+++ b/includes/lock.inc
@@ -195,12 +195,12 @@ function lock_may_be_available($name) {
  * @param $name
  *   The name of the lock.
  * @param $delay
- *   The maximum number of seconds to wait, as an integer.
+ *   The maximum number of seconds to wait, as a float.
  *
  * @return
  *   TRUE if the lock holds, FALSE if it is available.
  */
-function lock_wait($name, $delay = 30) {
+function lock_wait($name, $delay = 30.0) {
   // Pause the process for short periods between calling
   // lock_may_be_available(). This prevents hitting the database with constant
   // database queries while waiting, which could lead to performance issues.
@@ -214,7 +214,7 @@ function lock_wait($name, $delay = 30) {
   // $delay is passed in seconds, but we will be using usleep(), which takes
   // microseconds as a parameter. Multiply it by 1 million so that all
   // further numbers are equivalent.
-  $delay = (int) $delay * 1000000;
+  $delay = (int) ($delay * 1000000);
 
   // Begin sleeping at 25ms.
   $sleep = 25000;
