diff -uNr includes/bootstrap.inc includes/bootstrap.inc
--- includes/bootstrap.inc	2009-01-04 08:15:54.000000000 -0800
+++ includes/bootstrap.inc	2009-01-13 22:55:26.000000000 -0800
@@ -120,36 +120,41 @@
 define('DRUPAL_BOOTSTRAP_ACCESS', 3);
 
 /**
+ * Fifth bootstrap phase: initialize locking system.
+ */
+define('DRUPAL_BOOTSTRAP_LOCK', 4);
+
+/**
  * Fifth bootstrap phase: initialize session handling.
  */
-define('DRUPAL_BOOTSTRAP_SESSION', 4);
+define('DRUPAL_BOOTSTRAP_SESSION', 5);
 
 /**
  * Sixth bootstrap phase: initialize the variable system.
  */
-define('DRUPAL_BOOTSTRAP_VARIABLES', 5);
+define('DRUPAL_BOOTSTRAP_VARIABLES', 6);
 
 /**
  * Seventh bootstrap phase: load bootstrap.inc and module.inc, start
  * the variable system and try to serve a page from the cache.
  */
-define('DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE', 6);
+define('DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE', 7);
 
 /**
  * Eighth bootstrap phase: find out language of the page.
  */
-define('DRUPAL_BOOTSTRAP_LANGUAGE', 7);
+define('DRUPAL_BOOTSTRAP_LANGUAGE', 8);
 
 /**
  * Nineth bootstrap phase: set $_GET['q'] to Drupal path of request.
  */
-define('DRUPAL_BOOTSTRAP_PATH', 8);
+define('DRUPAL_BOOTSTRAP_PATH', 9);
 
 /**
  * Final bootstrap phase: Drupal is fully loaded; validate and fix
  * input data.
  */
-define('DRUPAL_BOOTSTRAP_FULL', 9);
+define('DRUPAL_BOOTSTRAP_FULL', 10);
 
 /**
  * Role ID for anonymous users; should match what's in the "role" table.
@@ -1049,6 +1054,7 @@
  *     DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE: try to call a non-database cache fetch routine.
  *     DRUPAL_BOOTSTRAP_DATABASE: initialize database layer.
  *     DRUPAL_BOOTSTRAP_ACCESS: identify and reject banned hosts.
+ *     DRUPAL_BOOTSTRAP_LOCK: initialize locking system.
  *     DRUPAL_BOOTSTRAP_SESSION: initialize session handling.
  *     DRUPAL_BOOTSTRAP_VARIABLES: initialize variable handling.
  *     DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE: load bootstrap.inc and module.inc, start
@@ -1058,7 +1064,7 @@
  *     DRUPAL_BOOTSTRAP_FULL: Drupal is fully loaded, validate and fix input data.
  */
 function drupal_bootstrap($phase = NULL) {
-  static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1;
+  static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_LOCK, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1;
 
   if (isset($phase)) {
     while ($phases && $phase > $completed_phase) {
@@ -1125,6 +1131,11 @@
       }
       break;
 
+    case DRUPAL_BOOTSTRAP_LOCK:
+      require_once variable_get('lock_inc', './includes/lock.inc');
+      lock_init();
+      break;
+
     case DRUPAL_BOOTSTRAP_SESSION:
       require_once DRUPAL_ROOT . '/' . variable_get('session_inc', 'includes/session.inc');
       session_set_save_handler('_sess_open', '_sess_close', '_sess_read', '_sess_write', '_sess_destroy_sid', '_sess_gc');
diff -uNr includes/lock.inc includes/lock.inc
--- includes/lock.inc	1969-12-31 16:00:00.000000000 -0800
+++ includes/lock.inc	2009-01-13 23:23:36.000000000 -0800
@@ -0,0 +1,101 @@
+<?php
+// $Id $
+
+/**
+ * @file
+ * Lock handling for concurrent requests.
+ */
+
+/**
+ * Initialize the locking system.
+ */
+function lock_init() {
+  global $locks;
+  $locks = array();
+  register_shutdown_function('lock_release_all');
+}
+
+/**
+ * Acquire a lock, do not block if it fails.
+ *
+ * @param $name
+ *   The name of the lock.
+ * @return TRUE if the lock was acquired, FALSE if it failed.
+ */
+function lock_acquire($name) {
+  global $locks;
+  if (isset($locks[$name])) {
+    return TRUE;
+  }
+  else {
+    // try to acquire the lock
+    $lock = cache_get($name, 'cache_lock');
+    if ($lock === FALSE) {
+      $locks[$name] = TRUE;
+      cache_set($name, $locks[$name], 'cache_lock', CACHE_TEMPORARY);
+      return TRUE;
+    }
+    else {
+      return FALSE;
+    }
+  }
+}
+
+/**
+ * Wait for a lock to be released.  We do this in ms so that we can wait a minimum
+ * of 1ms.  Typically you might want to lock for 100ms or so but not a full second.
+ * Be aware that locking and checking a server can put a pretty significant load on
+ * the cache server.
+ *
+ * @param $name
+ *   The name of the lock.
+ * @param $timeout
+ *   The timeout to wait for the lock in milliseconds (ms). Defaults to 2 seconds
+ * @param $interval
+ *   The amount of time to wait before checking for the lock again.  Defaults to 100ms.
+ * @return TRUE if the lock was acquired, FALSE if it failed.
+ */
+function lock_wait($name, $timeout = 2000, $interval = 100) {
+  global $locks;
+  if (isset($locks[$name])) {
+    return TRUE;
+  }
+  else {
+    list($start,) = explode(" ", microtime());
+    while (($lock = cache_get($name, 'cache_lock')) && $lock !== FALSE) {
+      usleep($interval * 1000);
+      list($time,) = explode(" ", microtime());
+      if ((($time - $start) * 1000) >= $timeout) {
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+}
+
+/**
+ * Release a lock previously acquired by lock_acquire().
+ *
+ * @param $name
+ *   The name of the lock.
+ */
+function lock_release($name) {
+  global $locks;
+  if (isset($locks[$name])) {
+    cache_clear_all($name, 'cache_lock');
+    unset($locks[$name]);
+  }
+}
+
+/**
+ * Release all previously acquired locks.
+ */
+function lock_release_all() {
+  global $locks;
+  if (!empty($locks)) {
+    foreach ($locks as $lock_id => $value) {
+      cache_clear_all($lock_id, 'cache_lock');
+      unset($locks[$lock_id]);
+    }
+  }
+}
\ No newline at end of file
diff -uNr includes/menu.inc includes/menu.inc
--- includes/menu.inc	2009-01-04 12:04:32.000000000 -0800
+++ includes/menu.inc	2009-01-13 22:51:01.000000000 -0800
@@ -1783,15 +1783,20 @@
  * is different and leaves stale data in the menu tables.
  */
 function menu_rebuild() {
+  if (!lock_acquire('menu_rebuild')) {
+    return FALSE;
+  }
   variable_del('menu_rebuild_needed');
   menu_cache_clear_all();
   $menu = menu_router_build(TRUE);
   _menu_navigation_links_rebuild($menu);
+  // Clear the menu cache after we have rebuild the router and navigation links
   // Clear the page and block caches.
   _menu_clear_page_cache();
   if (defined('MAINTENANCE_MODE')) {
     variable_set('menu_rebuild_needed', TRUE);
   }
+  lock_release('menu_rebuild');
 }
 
 /**
@@ -1799,7 +1804,6 @@
  */
 function menu_router_build($reset = FALSE) {
   static $menu;
-
   if (!isset($menu) || $reset) {
     if (!$reset && ($cache = cache_get('router:', 'cache_menu')) && isset($cache->data)) {
       $menu = $cache->data;
diff -uNr modules/locale/locale.module modules/locale/locale.module
--- modules/locale/locale.module	2008-12-16 15:57:32.000000000 -0800
+++ modules/locale/locale.module	2009-01-13 22:57:23.000000000 -0800
@@ -377,11 +377,14 @@
         // Refresh database stored cache of translations for given language.
         // We only store short strings used in current version, to improve
         // performance and consume less memory.
-        $result = db_query("SELECT s.source, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.textgroup = 'default' AND s.version = '%s' AND LENGTH(s.source) < 75", $langcode, VERSION);
-        while ($data = db_fetch_object($result)) {
-          $locale_t[$langcode][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
+        if (lock_acquire('locale_cache_' . $langcode)) {
+          $result = db_query("SELECT s.source, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.textgroup = 'default' AND s.version = '%s' AND LENGTH(s.source) < 75", $langcode, VERSION);
+          while ($data = db_fetch_object($result)) {
+            $locale_t[$langcode][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
+          }
+          cache_set('locale:' . $langcode, $locale_t[$langcode]);
+          lock_release('locale_cache_' . $langcode);
         }
-        cache_set('locale:' . $langcode, $locale_t[$langcode]);
       }
     }
   }
diff -uNr modules/system/system.install modules/system/system.install
--- modules/system/system.install	2009-01-13 23:06:18.000000000 -0800
+++ modules/system/system.install	2009-01-13 23:06:54.000000000 -0800
@@ -598,7 +598,9 @@
   $schema['cache_menu']['description'] = 'Cache table for the menu system to store router information as well as generated link trees for various menu/page/user combinations.';
   $schema['cache_registry'] = $schema['cache'];
   $schema['cache_registry']['description'] = 'Cache table for the code registry system to remember what code files need to be loaded on any given page.';
-
+  $schema['cache_lock'] = $schema['cache'];
+  $schema['cache_lock']['description'] = t('Cache table for the lock system to allow long operations without race conditions.');
+  
   $schema['files'] = array(
     'description' => 'Stores information for uploaded files.',
     'fields' => array(
