diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 111e89a..15bd250 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -296,12 +296,12 @@ abstract class DrupalCacheArray implements ArrayAccess {
   /**
    * A cid to pass to cache()->set() and cache()->get().
    */
-  private $cid;
+  protected $cid;
 
   /**
    * A bin to pass to cache()->set() and cache()->get().
    */
-  private $bin;
+  protected $bin;
 
   /**
    * An array of keys to add to the cache at the end of the request.
@@ -400,24 +400,20 @@ abstract class DrupalCacheArray implements ArrayAccess {
   /**
    * Writes a value to the persistent cache immediately.
    *
-   * @param $cid
-   *   The cache ID.
-   * @param $bin
-   *   The cache bin.
    * @param $data
    *   The data to write to the persistent cache.
    * @param $lock
    *   Whether to acquire a lock before writing to cache.
    */
-  protected function set($cid, $data, $bin, $lock = TRUE) {
+  protected function set($data, $lock = TRUE) {
     // Lock cache writes to help avoid stampedes.
     // To implement locking for cache misses, override __construct().
-    $lock_name = $cid . ':' . $bin;
+    $lock_name = $this->cid . ':' . $this->bin;
     if (!$lock || lock_acquire($lock_name)) {
-      if ($cached = cache($bin)->get($cid)) {
+      if ($cached = cache($this->bin)->get($this->cid)) {
         $data = $cached->data + $data;
       }
-      cache($bin)->set($cid, $data);
+      cache($bin)->set($this->cid, $data);
       if ($lock) {
         lock_release($lock_name);
       }
@@ -435,7 +431,7 @@ abstract class DrupalCacheArray implements ArrayAccess {
       }
     }
     if (!empty($data)) {
-      $this->set($this->cid, $data, $this->bin);
+      $this->set($data);
     }
   }
 }
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 3d19d3e..cf78fe1 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2336,7 +2336,7 @@ function l($text, $path, array $options = array()) {
     // rendering.
     if (variable_get('theme_link', TRUE)) {
       drupal_theme_initialize();
-      $registry = theme_get_registry();
+      $registry = theme_get_registry(FALSE);
       // We don't want to duplicate functionality that's in theme(), so any
       // hint of a module or theme doing anything at all special with the 'link'
       // theme hook should simply result in theme() being called. This includes
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 94d69d2..060d487 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -372,23 +372,31 @@ class ThemeRegistry Extends DrupalCacheArray {
       $data = $cached->data;
     }
     else {
-      $complete_registry = theme_get_registry();
+      // If there is no runtime cache stored, fetch the full theme registry,
+      // but then initialize each value to NULL. This allows offsetExists()
+      // to function correctly on non-registered theme hooks without triggering
+      // a call to resolveCacheMiss().
+      $data = $this->initializeRegistry();
       if ($this->persistable) {
-        // If there is no runtime cache stored, fetch the full theme registry,
-        // but then initialize each value to NULL. This allows
-        // offsetExists() to function correctly on non-registered theme hooks
-        // without triggering a call to resolveCacheMiss().
-        $data = array_fill_keys(array_keys($complete_registry), NULL);
-        $this->set($this->cid, $data, $this->bin);
-        $this->completeRegistry = $complete_registry;
-      }
-      else {
-        $data = $complete_registry;
+        $this->set($data);
       }
     }
     $this->storage = $data;
   }
 
+  /**
+   * Initializes the full theme registry.
+   *
+   * @return
+   *   An array with the keys of the full theme registry, but the values
+   *   initialized to NULL.
+   */
+  function initializeRegistry() {
+    $this->completeRegistry = theme_get_registry();
+
+    return array_fill_keys(array_keys($this->completeRegistry), NULL);
+  }
+
   public function offsetExists($offset) {
     // Since the theme registry allows for theme hooks to be requested that
     // are not registered, just check the existence of the key in the registry.
@@ -420,15 +428,19 @@ class ThemeRegistry Extends DrupalCacheArray {
     return $this->storage[$offset];
   }
 
-  public function set($cid, $data, $bin, $lock = TRUE) {
-    $lock_name = $cid . ':' . $bin;
+  public function set($data, $lock = TRUE) {
+    $lock_name = $this->cid . ':' . $this->bin;
     if (!$lock || lock_acquire($lock_name)) {
-      if ($cached = cache($bin)->get($cid)) {
+      if ($cached = cache($this->bin)->get($this->cid)) {
         // Use array merge instead of union so that filled in values in $data
         // overwrite empty values in the current cache.
         $data = array_merge($cached->data, $data);
       }
-      cache($bin)->set($cid, $data);
+      else {
+        $registry = $this->initializeRegistry();
+        $data = array_merge($registry, $data);
+      }
+      cache($this->bin)->set($this->cid, $data);
       if ($lock) {
         lock_release($lock_name);
       }
diff --git a/core/modules/simpletest/tests/theme.test b/core/modules/simpletest/tests/theme.test
index b47e379..2e18b73 100644
--- a/core/modules/simpletest/tests/theme.test
+++ b/core/modules/simpletest/tests/theme.test
@@ -540,3 +540,56 @@ class ThemeHtmlTplPhpAttributesTestCase extends DrupalWebTestCase {
     $this->assertTrue(count($attributes) == 1, t('Attribute set in the body element via hook_preprocess_html() found.'));
   }
 }
+
+/**
+ * Tests for the ThemeRegistry class.
+ */
+class ThemeRegistryTestCase extends DrupalWebTestCase {
+  protected $profile = 'testing';
+  public static function getInfo() {
+    return array(
+      'name' => 'ThemeRegistry',
+      'description' => 'Tests the behaviour of the ThemeRegistry class',
+      'group' => 'Theme',
+    );
+  }
+  function setUp() {
+    parent::setUp('theme_test');
+  }
+
+  /**
+   * Test the behaviour of the theme registry class.
+   */
+  function testRaceCondition() {
+    $_SERVER['REQUEST_METHOD'] = 'GET';
+    $cid = 'test_theme_registry';
+
+    // Directly instantiate the theme registry, this will cause a base cache
+    // entry to be written in __construct().
+    $registry = new ThemeRegistry($cid, 'cache');
+
+    // Confirm the cache entry was written.
+    $this->assertTrue(cache()->get($cid));
+
+    // Trigger a cache miss for an offset.
+    $this->assertTrue($registry['theme_test_template_test']);
+    // This will cause the ThemeRegistry class to write an updated version of
+    // the cache entry when it is destroyed, usually at the end of the request.
+    // Before that happens, manually delete the cache entry we created earlier
+    // so that the new entry is written from scratch.
+    cache()->delete($cid);
+
+    // Destroy the class so that it triggers a cache write for the offset.
+    unset($registry);
+
+    // Confirm a cache entry was written.
+    $this->assertTrue(cache()->get($cid));
+
+    // Create a new instance of the class. Confirm that both the offset
+    // requested previously, and one that has not yet been requested are both
+    // available.
+    $registry = new ThemeRegistry($cid, 'cache');
+    $this->assertTrue($registry['theme_test_template_test']);
+    $this->assertTrue($registry['theme_test_template_test_2']);
+  }
+}
diff --git a/core/modules/simpletest/tests/theme_test.module b/core/modules/simpletest/tests/theme_test.module
index 400902d..8c45e82 100644
--- a/core/modules/simpletest/tests/theme_test.module
+++ b/core/modules/simpletest/tests/theme_test.module
@@ -7,6 +7,9 @@ function theme_test_theme($existing, $type, $theme, $path) {
   $items['theme_test_template_test'] = array(
     'template' => 'theme_test.template_test',
   );
+  $items['theme_test_template_test_2'] = array(
+    'template' => 'theme_test.template_test',
+  );
 
   return $items;
 }
