diff --git a/core/core.services.yml b/core/core.services.yml
index 655bbe94e6e7a03fa325242ab3236c0ba6c913ef..db5240658f91dd22c4b2bd6b17bba326adce1cf9 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -450,6 +450,9 @@ services:
     arguments: ['@database']
     tags:
       - { name: backend_overridable }
+  lock.persistent:
+    class: Drupal\Core\Lock\PersistentDatabaseLockBackend
+    arguments: ['@database']
   router.request_context:
     class: Drupal\Core\Routing\RequestContext
     tags:
diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index 3efcd762e9629c3f50061dc8231d940be724053d..948330c5d4865934630aca3897ef0d0c5c9a373e 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -44,7 +44,7 @@ class ConfigImporter {
   /**
    * The name used to identify the lock.
    */
-  const LOCK_ID = 'config_importer';
+  const LOCK_NAME = 'config_importer';
 
   /**
    * The storage comparer used to discover configuration changes.
@@ -512,9 +512,9 @@ public function initialize() {
     // Ensure that the changes have been validated.
     $this->validate();
 
-    if (!$this->lock->acquire(static::LOCK_ID)) {
+    if (!$this->lock->acquire(static::LOCK_NAME)) {
       // Another process is synchronizing configuration.
-      throw new ConfigImporterException(sprintf('%s is already importing', static::LOCK_ID));
+      throw new ConfigImporterException(sprintf('%s is already importing', static::LOCK_NAME));
     }
 
     $sync_steps = array();
@@ -611,7 +611,7 @@ protected function processConfigurations(array &$context) {
   protected function finish(array &$context) {
     $this->eventDispatcher->dispatch(ConfigEvents::IMPORT, new ConfigImporterEvent($this));
     // The import is now complete.
-    $this->lock->release(static::LOCK_ID);
+    $this->lock->release(static::LOCK_NAME);
     $this->reset();
     $context['message'] = t('Finalizing configuration synchronization.');
     $context['finished'] = 1;
@@ -996,7 +996,7 @@ protected function importInvokeRename($collection, $rename_name) {
    *   TRUE if an import is already running, FALSE if not.
    */
   public function alreadyImporting() {
-    return !$this->lock->lockMayBeAvailable(static::LOCK_ID);
+    return !$this->lock->lockMayBeAvailable(static::LOCK_NAME);
   }
 
   /**
@@ -1007,13 +1007,13 @@ public function alreadyImporting() {
    * keep the services used by the importer in sync.
    */
   protected function reInjectMe() {
-    $this->eventDispatcher = \Drupal::service('event_dispatcher');
-    $this->configManager = \Drupal::service('config.manager');
-    $this->lock = \Drupal::lock();
-    $this->typedConfigManager = \Drupal::service('config.typed');
-    $this->moduleHandler = \Drupal::moduleHandler();
-    $this->themeHandler = \Drupal::service('theme_handler');
-    $this->stringTranslation = \Drupal::service('string_translation');
+    $this->_serviceIds = array();
+    $vars = get_object_vars($this);
+    foreach ($vars as $key => $value) {
+      if (is_object($value) && isset($value->_serviceId)) {
+        $this->$key = \Drupal::service($value->_serviceId);
+      }
+    }
   }
 
 }
diff --git a/core/lib/Drupal/Core/Lock/PersistentDatabaseLockBackend.php b/core/lib/Drupal/Core/Lock/PersistentDatabaseLockBackend.php
new file mode 100644
index 0000000000000000000000000000000000000000..6c7dfa246419a14045d84e754b0b3ae602f0cb96
--- /dev/null
+++ b/core/lib/Drupal/Core/Lock/PersistentDatabaseLockBackend.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Lock\PersistentDatabaseLockBackend.
+ */
+
+namespace Drupal\Core\Lock;
+
+use Drupal\Core\Database\Connection;
+
+/**
+ * Defines the persistent database lock backend. This backend is global for this
+ * Drupal installation.
+ *
+ * @ingroup lock
+ */
+class PersistentDatabaseLockBackend extends DatabaseLockBackend {
+
+  /**
+   * Constructs a new PersistentDatabaseLockBackend.
+   *
+   * @param \Drupal\Core\Database\Connection $database
+   *   The database connection.
+   */
+  public function __construct(Connection $database) {
+    // Do not call the parent constructor to avoid registering a shutdown
+    // function that releases all the locks at the end of a request.
+    $this->database = $database;
+    // Set the lockId to a fixed string to make the lock ID the same across
+    // multiple requests. The lock ID is used as a page token to relate all the
+    // locks set during a request to each other.
+    // @see \Drupal\Core\Lock\LockBackendInterface::getLockId()
+    $this->lockId = 'persistent';
+  }
+}
diff --git a/core/modules/config/src/Form/ConfigSync.php b/core/modules/config/src/Form/ConfigSync.php
index 21840a5ce6334812a565b5a71f8431267c68e104..b99c2903bde911cc3a84418eaa01852d3f8549f9 100644
--- a/core/modules/config/src/Form/ConfigSync.php
+++ b/core/modules/config/src/Form/ConfigSync.php
@@ -134,7 +134,7 @@ public static function create(ContainerInterface $container) {
       $container->get('config.storage.staging'),
       $container->get('config.storage'),
       $container->get('config.storage.snapshot'),
-      $container->get('lock'),
+      $container->get('lock.persistent'),
       $container->get('event_dispatcher'),
       $container->get('config.manager'),
       $container->get('config.typed'),
diff --git a/core/modules/config/src/Tests/ConfigImportRenameValidationTest.php b/core/modules/config/src/Tests/ConfigImportRenameValidationTest.php
index 60aab7fb41ede9b1aa5bdd2e510f126bc31ee29c..fc0d0ed565e50845cbbc6469c66dc45b62542fc8 100644
--- a/core/modules/config/src/Tests/ConfigImportRenameValidationTest.php
+++ b/core/modules/config/src/Tests/ConfigImportRenameValidationTest.php
@@ -55,7 +55,7 @@ protected function setUp() {
       $storage_comparer->createChangelist(),
       $this->container->get('event_dispatcher'),
       $this->container->get('config.manager'),
-      $this->container->get('lock'),
+      $this->container->get('lock.persistent'),
       $this->container->get('config.typed'),
       $this->container->get('module_handler'),
       $this->container->get('theme_handler'),
diff --git a/core/modules/config/src/Tests/ConfigImportUITest.php b/core/modules/config/src/Tests/ConfigImportUITest.php
index 20187161c6629cdeb7b2a9f5c128bca6e5ae90aa..f3a7f398053ec85c0823a7a3354ef64480fc8911 100644
--- a/core/modules/config/src/Tests/ConfigImportUITest.php
+++ b/core/modules/config/src/Tests/ConfigImportUITest.php
@@ -228,14 +228,14 @@ function testImportLock() {
 
     // Acquire a fake-lock on the import mechanism.
     $config_importer = $this->configImporter();
-    $this->container->get('lock')->acquire($config_importer::LOCK_ID);
+    $this->container->get('lock.persistent')->acquire($config_importer::LOCK_NAME);
 
     // Attempt to import configuration and verify that an error message appears.
     $this->drupalPostForm(NULL, array(), t('Import all'));
     $this->assertText(t('Another request may be synchronizing configuration already.'));
 
     // Release the lock, just to keep testing sane.
-    $this->container->get('lock')->release($config_importer::LOCK_ID);
+    $this->container->get('lock.persistent')->release($config_importer::LOCK_NAME);
 
     // Verify site name has not changed.
     $this->assertNotEqual($new_site_name, \Drupal::config('system.site')->get('name'));
diff --git a/core/modules/config/src/Tests/ConfigImporterTest.php b/core/modules/config/src/Tests/ConfigImporterTest.php
index eff180c4c9a9242c1422ffef29b38af50d92b1b5..6e003974bede8748daaadca01af423f9c2234b09 100644
--- a/core/modules/config/src/Tests/ConfigImporterTest.php
+++ b/core/modules/config/src/Tests/ConfigImporterTest.php
@@ -527,4 +527,3 @@ function testUpdated() {
     $this->assertEqual(count($logs), 0);
   }
 }
-
diff --git a/core/modules/system/src/Tests/Lock/LockFunctionalTest.php b/core/modules/system/src/Tests/Lock/LockFunctionalTest.php
index 6b1518cdb322aaa5f1bef12eba21caee350e95f4..846b44db3b100b8687aea0d934cc1ad1ea75219b 100644
--- a/core/modules/system/src/Tests/Lock/LockFunctionalTest.php
+++ b/core/modules/system/src/Tests/Lock/LockFunctionalTest.php
@@ -59,4 +59,29 @@ public function testLockAcquire() {
     $this->assertText($lock_acquired_exit, 'Lock acquired by the other request before exit.', 'Lock');
     $this->assertTrue($lock->acquire('system_test_lock_exit'), 'Lock acquired by this request after the other request exits.', 'Lock');
   }
+
+  /**
+   * Tests that the persistent lock is persisted between requests.
+   */
+  public function testPersistentLock() {
+    $persistent_lock = $this->container->get('lock.persistent');
+    // Get a persistent lock.
+    $this->drupalGet('system-test/lock-persist/lock1');
+    $this->assertText('TRUE: Lock successfully acquired in SystemTestController::lockPersist()');
+    // Ensure that a shutdown function has not released the lock.
+    $this->assertFalse($persistent_lock->lockMayBeAvailable('lock1'));
+    $this->drupalGet('system-test/lock-persist/lock1');
+    $this->assertText('FALSE: Lock not acquired in SystemTestController::lockPersist()');
+
+    // Get another persistent lock.
+    $this->drupalGet('system-test/lock-persist/lock2');
+    $this->assertText('TRUE: Lock successfully acquired in SystemTestController::lockPersist()');
+    $this->assertFalse($persistent_lock->lockMayBeAvailable('lock2'));
+
+    // Release the first lock and try getting it again.
+    $persistent_lock->release('lock1');
+    $this->drupalGet('system-test/lock-persist/lock1');
+    $this->assertText('TRUE: Lock successfully acquired in SystemTestController::lockPersist()');
+  }
+
 }
diff --git a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
index dd04e6c1cab1c925e53d1d1f439fcc0faf77fe31..c6b6903ac12381579d7e159e60c153947be9f287 100644
--- a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
+++ b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
@@ -10,12 +10,38 @@
 use Drupal\Core\Controller\ControllerBase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
+use Drupal\Core\Lock\LockBackendInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Controller routines for system_test routes.
  */
 class SystemTestController extends ControllerBase {
 
+  /**
+   * The persistent lock service.
+   *
+   * @var \Drupal\Core\Lock\LockBackendInterface
+   */
+  protected $persistentLock;
+
+  /**
+   * Constructs the SystemTestController.
+   *
+   * @param \Drupal\Core\Lock\LockBackendInterface $persistent_lock
+   *   The persistent lock service.
+   */
+  public function __construct(LockBackendInterface $persistent_lock) {
+    $this->persistentLock = $persistent_lock;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static($container->get('lock.persistent'));
+  }
+
   /**
    * Tests main content fallback.
    *
@@ -56,6 +82,24 @@ public function lockExit() {
     return system_test_lock_exit();
   }
 
+  /**
+   * Creates a lock that will persist across requests.
+   *
+   * @param string $lock_name
+   *   The name of the persistent lock to acquire.
+   *
+   * @return string
+   *   The text to display.
+   */
+  public function lockPersist($lock_name) {
+    if ($this->persistentLock->acquire($lock_name)) {
+      return 'TRUE: Lock successfully acquired in SystemTestController::lockPersist()';
+    }
+    else {
+      return 'FALSE: Lock not acquired in SystemTestController::lockPersist()';
+    }
+  }
+
   /**
    * Set cache tag on on the returned render array.
    */
diff --git a/core/modules/system/tests/modules/system_test/system_test.routing.yml b/core/modules/system/tests/modules/system_test/system_test.routing.yml
index 32d235bab9faa27d30deed1b33eedec090232a67..530a2ca28b295856597d257e2105f6c8cffcd967 100644
--- a/core/modules/system/tests/modules/system_test/system_test.routing.yml
+++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml
@@ -53,6 +53,14 @@ system_test.lock_exit:
   requirements:
     _access: 'TRUE'
 
+system_test.lock_persist:
+  path: '/system-test/lock-persist/{lock_name}'
+  defaults:
+    _title: 'Persistent lock acquire'
+    _content: '\Drupal\system_test\Controller\SystemTestController::lockPersist'
+  requirements:
+    _access: 'TRUE'
+
 system_test.cache_tags_page:
   path: '/system-test/cache_tags_page'
   defaults: