Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.406
diff -u -p -r1.406 bootstrap.inc
--- includes/bootstrap.inc	7 Jul 2010 17:53:28 -0000	1.406
+++ includes/bootstrap.inc	8 Jul 2010 07:47:55 -0000
@@ -874,6 +874,21 @@ function drupal_page_get_cache($check_on
     if ($cache !== FALSE) {
       $cache_hit = TRUE;
     }
+    else {
+      // Cache miss. Avoid a stampede.
+      $name = $GLOBALS['base_root'] . request_uri();
+      if (!lock_acquire($name, 1)) {
+        // Another request is building the page cache.
+        // Wait, then re-run this function.
+        header('X-Drupal-Cache: WAIT');
+        lock_wait($name);
+        return drupal_page_get_cache();
+      }
+      else {
+        // Proceed with page build;  cache its result, then release the lock.
+        header('X-Drupal-Cache: MISS');
+      }
+    }
     return $cache;
   }
 }
@@ -2141,9 +2156,6 @@ function _drupal_bootstrap_page_cache() 
       // We are done.
       exit;
     }
-    else {
-      header('X-Drupal-Cache: MISS');
-    }
   }
 }
 
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1191
diff -u -p -r1.1191 common.inc
--- includes/common.inc	7 Jul 2010 17:00:42 -0000	1.1191
+++ includes/common.inc	8 Jul 2010 07:47:58 -0000
@@ -4607,6 +4607,7 @@ function drupal_page_set_cache() {
         $cache->data['body'] = gzencode($cache->data['body'], 9, FORCE_GZIP);
       }
       cache_set($cache->cid, $cache->data, 'cache_page', $cache->expire);
+      lock_release($cache->cid);
     }
     return $cache;
   }
@@ -5235,7 +5236,7 @@ function drupal_render_cache_get($elemen
   }
   $bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'cache';
 
-  if (!empty($cid) && $cache = cache_get($cid, $bin)) {
+  if ($cache = cache_get($cid, $bin)) {
     // Add additional libraries, JavaScript, CSS and other data attached
     // to this element.
     if (isset($cache->data['#attached'])) {
@@ -5244,7 +5245,19 @@ function drupal_render_cache_get($elemen
     // Return the rendered output.
     return $cache->data['#markup'];
   }
-  return FALSE;
+  else {
+    // Cache miss. Avoid a stampede.
+    if (!lock_acquire($cid, 1)) {
+      // Another request is building this cache entry.
+      // Wait, then re-run this function.
+      lock_wait($cid);
+      return drupal_render_cache_get($elements);
+    }
+    else {
+      // Proceed with rendering, cache the result, and then release the lock.
+      return FALSE;
+    }
+  }
 }
 
 /**
@@ -5280,6 +5293,7 @@ function drupal_render_cache_set(&$marku
   $bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'cache';
   $expire = isset($elements['#cache']['expire']) ? $elements['#cache']['expire'] : CACHE_PERMANENT;
   cache_set($cid, $data, $bin, $expire);
+  lock_release($cid);
 }
 
 /**
Index: includes/lock.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/lock.inc,v
retrieving revision 1.4
diff -u -p -r1.4 lock.inc
--- includes/lock.inc	6 May 2010 15:20:18 -0000	1.4
+++ includes/lock.inc	8 Jul 2010 07:47:59 -0000
@@ -195,11 +195,16 @@ function lock_may_be_available($name) {
  */
 function lock_wait($name, $delay = 30) {
   $delay = (int) $delay;
-  while ($delay--) {
+  $sleep = 1;
+  while ($delay > 0) {
     // This function should only be called by a request that failed to get a
     // lock, so we sleep first to give the parallel request a chance to finish
     // and release the lock.
-    sleep(1);
+    sleep($sleep);
+    // After each sleep, double the value of $sleep, to reduce the potential
+    // for a lock stampede.
+    $delay = $delay - $sleep;
+    $sleep = min($sleep * 2, $delay);
     if (lock_may_be_available($name)) {
       // No longer need to wait.
       return FALSE;
