diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index edbe0b7..30ee070 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -981,7 +981,8 @@ function variable_initialize($conf = array()) {
   else {
     // Cache miss. Avoid a stampede.
     $name = 'variable_init';
-    if (!lock()->acquire($name, 1)) {
+    $lock = lock()->acquire($name, 1);
+    if (!$lock) {
       // Another request is building the variable cache.
       // Wait, then re-run this function.
       lock()->wait($name);
@@ -991,7 +992,7 @@ function variable_initialize($conf = array()) {
       // Proceed with variable rebuild.
       $variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed());
       cache('bootstrap')->set('variables', $variables);
-      lock()->release($name);
+      $lock->release();
     }
   }
 
@@ -3516,19 +3517,20 @@ function drupal_check_memory_limit($required, $memory_limit = NULL) {
  * this API:
  * @code
  * function mymodule_long_operation() {
- *   if (lock()->acquire('mymodule_long_operation')) {
+ *   $lock = lock()->acquire('mymodule_long_operation');
+ *   if ($lock) {
  *     // Do the long operation here.
  *     // ...
- *     lock()->release('mymodule_long_operation');
+ *     $lock->release();
  *   }
  * }
  * @endcode
  *
- * If a function acquires a lock it should always release it when the
- * operation is complete by calling lock()->release(), as in the example.
+ * If a function acquires a lock and does not release it explicitly by calling
+ * $lock->release(), it is automatically released when $lock goes out of scope.
  *
  * A function that has acquired a lock may attempt to renew a lock (extend the
- * duration of the lock) by calling lock()->acquire() again during the operation.
+ * duration of the lock) by calling lock()->nenew() during the operation.
  * Failure to renew a lock is indicative that another request has acquired
  * the lock, and that the current operation may need to be aborted.
  *
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 97b73f4..43dc0c7 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -4976,7 +4976,8 @@ function drupal_cron_run() {
   drupal_alter('queue_info', $queues);
 
   // Try to acquire cron lock.
-  if (!lock()->acquire('cron', 240.0)) {
+  $lock = lock()->acquire('cron', 240.0);
+  if (!$lock) {
     // Cron is still running normally.
     watchdog('cron', 'Attempting to re-run cron while it is already running.', array(), WATCHDOG_WARNING);
   }
@@ -5005,7 +5006,7 @@ function drupal_cron_run() {
     watchdog('cron', 'Cron run completed.', array(), WATCHDOG_NOTICE);
 
     // Release cron lock.
-    lock()->release('cron');
+    $lock->release();
 
     // Return TRUE so other functions can check if it did run successfully
     $return = TRUE;
diff --git a/core/includes/config.inc b/core/includes/config.inc
index b4a0666..d00d22a 100644
--- a/core/includes/config.inc
+++ b/core/includes/config.inc
@@ -207,7 +207,8 @@ function config_import() {
     return;
   }
 
-  if (!lock()->acquire(CONFIG_IMPORT_LOCK)) {
+  $lock = lock()->acquire(CONFIG_IMPORT_LOCK);
+  if (!$lock) {
     // Another request is synchronizing configuration.
     // Return a negative result for UI purposes. We do not differentiate between
     // an actual synchronization error and a failed lock, because concurrent
@@ -225,7 +226,7 @@ function config_import() {
     watchdog_exception('config_import', $e);
     $success = FALSE;
   }
-  lock()->release(CONFIG_IMPORT_LOCK);
+  $lock->release();
 
   return $success;
 }
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index 3ef5442..5c83080 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -2655,7 +2655,8 @@ function menu_reset_static_cache() {
  *   in parallel and the current thread just waited for completion.
  */
 function menu_router_rebuild() {
-  if (!lock()->acquire(__FUNCTION__)) {
+  $lock = lock()->acquire(__FUNCTION__);
+  if (!$lock) {
     // Wait for another request that is already doing this work.
     // We choose to block here since otherwise the router item may not
     // be available during routing resulting in a 404.
@@ -2680,7 +2681,6 @@ function menu_router_rebuild() {
     watchdog_exception('menu', $e);
   }
 
-  lock()->release(__FUNCTION__);
   return TRUE;
 }
 
diff --git a/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php b/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php
index 44251e3..c05d5bf 100644
--- a/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php
+++ b/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php
@@ -15,69 +15,6 @@
 class DatabaseLockBackend extends LockBackendAbstract {
 
   /**
-   * Constructs a new DatabaseLockBackend.
-   */
-  public function __construct() {
-    // __destruct() is causing problems with garbage collections, register a
-    // shutdown function instead.
-    drupal_register_shutdown_function(array($this, 'releaseAll'));
-  }
-
-  /**
-   * Implements Drupal\Core\Lock\LockBackedInterface::acquire().
-   */
-  public function acquire($name, $timeout = 30.0) {
-    // Insure that the timeout is at least 1 ms.
-    $timeout = max($timeout, 0.001);
-    $expire = microtime(TRUE) + $timeout;
-    if (isset($this->locks[$name])) {
-      // Try to extend the expiration of a lock we already acquired.
-      $success = (bool) db_update('semaphore')
-        ->fields(array('expire' => $expire))
-        ->condition('name', $name)
-        ->condition('value', $this->getLockId())
-        ->execute();
-      if (!$success) {
-        // The lock was broken.
-        unset($this->locks[$name]);
-      }
-      return $success;
-    }
-    else {
-      // Optimistically try to acquire the lock, then retry once if it fails.
-      // The first time through the loop cannot be a retry.
-      $retry = FALSE;
-      // We always want to do this code at least once.
-      do {
-        try {
-          db_insert('semaphore')
-            ->fields(array(
-              'name' => $name,
-              'value' => $this->getLockId(),
-              'expire' => $expire,
-            ))
-            ->execute();
-          // We track all acquired locks in the global variable.
-          $this->locks[$name] = TRUE;
-          // We never need to try again.
-          $retry = FALSE;
-        }
-        catch (IntegrityConstraintViolationException $e) {
-          // Suppress the error. If this is our first pass through the loop,
-          // then $retry is FALSE. In this case, the insert failed because some
-          // other request acquired the lock but did not release it. We decide
-          // whether to retry by checking lockMayBeAvailable(). This will clear
-          // the offending row from the database table in case it has expired.
-          $retry = $retry ? FALSE : $this->lockMayBeAvailable($name);
-        }
-        // We only retry in case the first attempt failed, but we then broke
-        // an expired lock.
-      } while ($retry);
-    }
-    return isset($this->locks[$name]);
-  }
-
-  /**
    * Implements Drupal\Core\Lock\LockBackedInterface::lockMayBeAvailable().
    */
   public function lockMayBeAvailable($name) {
@@ -101,26 +38,64 @@ class DatabaseLockBackend extends LockBackendAbstract {
   }
 
   /**
-   * Implements Drupal\Core\Lock\LockBackedInterface::release().
+   * Implements Drupal\Core\Lock\LockBackedInterface::acquire().
+   */
+  public function acquire($name, $timeout = 30.0) {
+    // Optimistically try to acquire the lock, then retry once if it fails.
+    // The first time through the loop cannot be a retry.
+    $retry = FALSE;
+    $expire = microtime(TRUE) + $timeout;
+    // We always want to do this code at least once.
+    do {
+      try {
+        $lockId = $this->getNewLockId();
+        db_insert('semaphore')
+          ->fields(array(
+            'name' => $name,
+            'value' => $lockId,
+            'expire' => $expire,
+          ))
+          ->execute();
+        // We track all acquired locks in the global variable.
+        return new Lock($this, $name, $lockId);
+      }
+      catch (IntegrityConstraintViolationException $e) {
+        // Suppress the error. If this is our first pass through the loop,
+        // then $retry is FALSE. In this case, the insert failed because some
+        // other request acquired the lock but did not release it. We decide
+        // whether to retry by checking lockMayBeAvailable(). This will clear
+        // the offending row from the database table in case it has expired.
+        $retry = $retry ? FALSE : $this->lockMayBeAvailable($name);
+      }
+      // We only retry in case the first attempt failed, but we then broke
+      // an expired lock.
+    } while ($retry);
+    return FALSE;
+  }
+
+  /**
+   * Implements Drupal\Core\Lock\LockBackedInterface::renew().
    */
-  public function release($name) {
-    unset($this->locks[$name]);
-    db_delete('semaphore')
-      ->condition('name', $name)
-      ->condition('value', $this->getLockId())
+  public function renew(Lock $lock, $timeout) {
+    // Ensure that the timeout is at least 1 ms.
+    $timeout = max($timeout, 0.001);
+    $expire = microtime(TRUE) + $timeout;
+
+    // Try to extend the expiration of a lock we already acquired.
+    return (bool) db_update('semaphore')
+      ->fields(array('expire' => $expire))
+      ->condition('name', $lock->name())
+      ->condition('value', $lock->lockId())
       ->execute();
   }
 
   /**
-   * Implements Drupal\Core\Lock\LockBackedInterface::releaseAll().
+   * Implements Drupal\Core\Lock\LockBackedInterface::release().
    */
-  public function releaseAll($lock_id = NULL) {
-    $this->locks = array();
-    if (empty($lock_id)) {
-      $lock_id = $this->getLockId();
-    }
-    db_delete('semaphore')
-      ->condition('value', $lock_id)
+  public function release(Lock $lock) {
+    return (bool) db_delete('semaphore')
+      ->condition('name', $lock->name())
+      ->condition('value', $lock->lockId())
       ->execute();
   }
 }
diff --git a/core/lib/Drupal/Core/Lock/Lock.php b/core/lib/Drupal/Core/Lock/Lock.php
new file mode 100644
index 0000000..0cc2dc0
--- /dev/null
+++ b/core/lib/Drupal/Core/Lock/Lock.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Lock\Lock.
+ */
+
+namespace Drupal\Core\Lock;
+
+/**
+ * Lock token. This object is created when a lock is acquired throught the
+ * factory. This object acts as the lock holder and will release automatically
+ * the lock upon destruction acting as both a code shortcut and a safeguard
+ * avoiding lock stall.
+ */
+class Lock {
+
+  /**
+   * @var LockBackendInterface
+   */
+  protected $backend;
+
+  /**
+   * @var string
+   */
+  protected $name;
+
+  /**
+   * @var string
+   */
+  protected $lockId;
+
+  /**
+   * @var bool
+   */
+  protected $autoRelease = TRUE;
+
+  /**
+   * Has this instance lock been released.
+   *
+   * @var bool
+   */
+  protected $released = FALSE;
+
+  /**
+   * Default constructor.
+   *
+   * @param LockBackendInterface $backend
+   * @param string $name
+   * @param bool $enableAutoRelease = TRUE
+   */
+  public function __construct($backend, $name, $lock_id) {
+    $this->backend = $backend;
+    $this->name = $name;
+    $this->lockId = $lock_id;
+  }
+
+  /**
+   * Returns the name of this lock.
+   *
+   * @return string
+   */
+  public function name() {
+    return $this->name;
+  }
+
+  /**
+   * Returns the ID of this lock.
+   *
+   * @return string
+   */
+  public function lockId() {
+    return $this->lockId;
+  }
+
+  /**
+   * Renew this lock.
+   *
+   * @param float $timeout
+   *   New lock lifetime in seconds.
+   */
+  public function renew($timeout = 30.0) {
+    return $this->backend->renew($this, $timeout);
+  }
+
+  /**
+   * Release this lock.
+   */
+  public function release() {
+    $this->released = $this->backend->release($this);
+    return $this->released;
+  }
+
+  /**
+   * Disable auto lock release when token goes out of scope.
+   */
+  public function autoRelease($auto_release) {
+    $this->autoRelease = $auto_release;
+  }
+
+  /**
+   * Default destructor.
+   */
+  public function __destruct() {
+    if (!$this->released && $this->autoRelease) {
+      $this->release();
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Lock/LockBackendAbstract.php b/core/lib/Drupal/Core/Lock/LockBackendAbstract.php
index f6ca89c..a5e2647 100644
--- a/core/lib/Drupal/Core/Lock/LockBackendAbstract.php
+++ b/core/lib/Drupal/Core/Lock/LockBackendAbstract.php
@@ -13,20 +13,6 @@
 abstract class LockBackendAbstract implements LockBackendInterface {
 
   /**
-   * Current page lock token identifier.
-   *
-   * @var string
-   */
-  protected $lockId;
-
-  /**
-   * Existing locks for this page.
-   *
-   * @var array
-   */
-  protected $locks = array();
-
-  /**
    * Implements Drupal\Core\Lock\LockBackedInterface::wait().
    */
   public function wait($name, $delay = 30) {
@@ -66,12 +52,14 @@
   }
 
   /**
-   * Implements Drupal\Core\Lock\LockBackedInterface::getLockId().
+   * Returns a new unique lock ID.
    */
-  public function getLockId() {
-    if (!isset($this->lockId)) {
-      $this->lockId = uniqid(mt_rand(), TRUE);
+  protected function getNewLockId() {
+    $base = &drupal_static('Drupal\Core\Lock\LockBackendAbstract::base');
+    $count = &drupal_static('Drupal\Core\Lock\LockBackendAbstract::count', 0);
+    if (!isset($base)) {
+      $base = uniqid(mt_rand(), TRUE);
     }
-    return $this->lockId;
+    return $base . '-' . $count++;
   }
 }
diff --git a/core/lib/Drupal/Core/Lock/LockBackendInterface.php b/core/lib/Drupal/Core/Lock/LockBackendInterface.php
index 01ca219..28fcae4 100644
--- a/core/lib/Drupal/Core/Lock/LockBackendInterface.php
+++ b/core/lib/Drupal/Core/Lock/LockBackendInterface.php
@@ -13,18 +13,6 @@
 interface LockBackendInterface {
 
   /**
-   * Acquires a lock.
-   *
-   * @param string $name
-   *   Lock name.
-   * @param float $timeout = 30.0
-   *   (optional) Lock lifetime in seconds.
-   *
-   * @return bool
-   */
-  public function acquire($name, $timeout = 30.0);
-
-  /**
    * Checks if a lock is available for acquiring.
    *
    * @param string $name
@@ -45,7 +33,7 @@
    * @param string $name
    *   Lock name currently being locked.
    * @param int $delay = 30
-   *   Miliseconds to wait for.
+   *   Milliseconds to wait for.
    *
    * @return bool
    *   TRUE if the wait operation was successful and lock may be available. You
@@ -54,26 +42,31 @@
   public function wait($name, $delay = 30);
 
   /**
-   * Releases the given lock.
+   * Acquires a lock.
    *
    * @param string $name
+   *   Lock name.
+   * @param float $timeout
+   *   Lock lifetime in seconds.
+   *
+   * @return Drupal\Core\Lock\Lock|false
    */
-  public function release($name);
+  public function acquire($name, $timeout);
 
   /**
-   * Releases all locks for the given lock token identifier.
+   * Renews an already required lock.
    *
-   * @param string $lockId
-   *   (optional) If none given, remove all locks from the current page.
-   *   Defaults to NULL.
+   * @param string $name
+   *   Lock name.
+   * @param float $timeout
+   *   New lock lifetime in seconds.
    */
-  public function releaseAll($lockId = NULL);
+  public function renew(Lock $lock, $timeout);
 
   /**
-   * Gets the unique page token for locks. Locks will be wipeout at each end of
-   * page request on a token basis.
+   * Releases the given lock.
    *
-   * @return string
+   * @param string $name
    */
-  public function getLockId();
+  public function release(Lock $lock);
 }
diff --git a/core/lib/Drupal/Core/Lock/NullLockBackend.php b/core/lib/Drupal/Core/Lock/NullLockBackend.php
index bd59888..c63a6ec 100644
--- a/core/lib/Drupal/Core/Lock/NullLockBackend.php
+++ b/core/lib/Drupal/Core/Lock/NullLockBackend.php
@@ -16,20 +16,6 @@
 class NullLockBackend implements LockBackendInterface {
 
   /**
-   * Current page lock token identifier.
-   *
-   * @var string
-   */
-  protected $lockId;
-
-  /**
-   * Implements Drupal\Core\Lock\LockBackedInterface::acquire().
-   */
-  public function acquire($name, $timeout = 30.0) {
-    return TRUE;
-  }
-
-  /**
    * Implements Drupal\Core\Lock\LockBackedInterface::lockMayBeAvailable().
    */
   public function lockMayBeAvailable($name) {
@@ -42,22 +28,23 @@ class NullLockBackend implements LockBackendInterface {
   public function wait($name, $delay = 30) {}
 
   /**
-   * Implements Drupal\Core\Lock\LockBackedInterface::release().
+   * Implements Drupal\Core\Lock\LockBackedInterface::acquire().
    */
-  public function release($name) {}
+  public function acquire($name, $timeout = 30.0) {
+    return new Lock($this, $name, 'dummy');
+  }
 
   /**
-   * Implements Drupal\Core\Lock\LockBackedInterface::releaseAll().
+   * Implements Drupal\Core\Lock\LockBackedInterface::renew().
    */
-  public function releaseAll($lock_id = NULL) {}
+  public function renew(Lock $lock, $timeout) {
+    return TRUE;
+  }
 
   /**
-   * Implements Drupal\Core\Lock\LockBackedInterface::getLockId().
+   * Implements Drupal\Core\Lock\LockBackedInterface::release().
    */
-  public function getLockId() {
-    if (!isset($this->lockId)) {
-      $this->lockId = uniqid(mt_rand(), TRUE);
-    }
-    return $this->lockId;
+  public function release(Lock $lock) {
+    return TRUE;
   }
 }
diff --git a/core/lib/Drupal/Core/Routing/RouteBuilder.php b/core/lib/Drupal/Core/Routing/RouteBuilder.php
index 232e47e..e5ac587 100644
--- a/core/lib/Drupal/Core/Routing/RouteBuilder.php
+++ b/core/lib/Drupal/Core/Routing/RouteBuilder.php
@@ -34,9 +34,9 @@ class RouteBuilder {
   /**
    * The used lock backend instance.
    *
-   * @var \Drupal\Core\Lock\LockBackendInterface $lock
+   * @var \Drupal\Core\Lock\LockBackendInterface $lockBackend
    */
-  protected $lock;
+  protected $lockBackend;
 
   /**
    * The event dispatcher to notify of routes.
@@ -62,9 +62,9 @@ class RouteBuilder {
    * @param \Symfony\Component\EventDispatcherEventDispatcherInterface
    *   The event dispatcher to notify of routes.
    */
-  public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher, ModuleHandlerInterface $module_handler) {
+  public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lockBackend, EventDispatcherInterface $dispatcher, ModuleHandlerInterface $module_handler) {
     $this->dumper = $dumper;
-    $this->lock = $lock;
+    $this->lockBackend = $lockBackend;
     $this->dispatcher = $dispatcher;
     $this->moduleHandler = $module_handler;
   }
@@ -73,11 +73,12 @@ class RouteBuilder {
    * Rebuilds the route info and dumps to dumper.
    */
   public function rebuild() {
-    if (!$this->lock->acquire('router_rebuild')) {
+    $lock = $this->lockBackend->acquire('router_rebuild');
+    if (!$lock) {
       // Wait for another request that is already doing this work.
       // We choose to block here since otherwise the routes might not be
       // available, resulting in a 404.
-      $this->lock->wait('router_rebuild');
+      $this->lockBackend->wait('router_rebuild');
       return;
     }
 
@@ -112,7 +113,7 @@ class RouteBuilder {
     $this->dumper->addRoutes($collection);
     $this->dumper->dump(array('route_set' => 'dynamic_routes'));
 
-    $this->lock->release('router_rebuild');
+    $lock->release('router_rebuild');
   }
 
 }
diff --git a/core/lib/Drupal/Core/Utility/CacheArray.php b/core/lib/Drupal/Core/Utility/CacheArray.php
index eddfc27..88c620b 100644
--- a/core/lib/Drupal/Core/Utility/CacheArray.php
+++ b/core/lib/Drupal/Core/Utility/CacheArray.php
@@ -200,13 +200,13 @@
     // Lock cache writes to help avoid stampedes.
     // To implement locking for cache misses, override __construct().
     $lock_name = $this->cid . ':' . $this->bin;
-    if (!$lock || lock()->acquire($lock_name)) {
+    if (!$lock || $lock_object = lock()->acquire($lock_name)) {
       if ($cached = cache($this->bin)->get($this->cid)) {
         $data = $cached->data + $data;
       }
       cache($this->bin)->set($this->cid, $data, CacheBackendInterface::CACHE_PERMANENT, $this->tags);
-      if ($lock) {
-        lock()->release($lock_name);
+      if ($lock_object) {
+        $lock_object->release();
       }
     }
   }
diff --git a/core/lib/Drupal/Core/Utility/ThemeRegistry.php b/core/lib/Drupal/Core/Utility/ThemeRegistry.php
index eb2dd80..ee1724b 100644
--- a/core/lib/Drupal/Core/Utility/ThemeRegistry.php
+++ b/core/lib/Drupal/Core/Utility/ThemeRegistry.php
@@ -126,7 +126,7 @@ function initializeRegistry() {
    */
   public function set($data, $lock = TRUE) {
     $lock_name = $this->cid . ':' . $this->bin;
-    if (!$lock || lock()->acquire($lock_name)) {
+    if (!$lock || $lock_object = lock()->acquire($lock_name)) {
       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.
@@ -137,8 +137,8 @@ function initializeRegistry() {
         $data = array_merge($registry, $data);
       }
       cache($this->bin)->set($this->cid, $data, CacheBackendInterface::CACHE_PERMANENT, $this->tags);
-      if ($lock) {
-        lock()->release($lock_name);
+      if ($lock_object) {
+        $lock_object->release();
       }
     }
   }
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
index 6851be0..f3be5cb 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
@@ -20,9 +20,9 @@
  */
 class CommentStorageController extends DatabaseStorageControllerNG {
   /**
-   * The thread for which a lock was acquired.
+   * Lock acquired during presave.
    */
-  protected $threadLock = '';
+  protected $threadLock = NULL;
 
   /**
    * Overrides Drupal\Core\Entity\DatabaseStorageController::buildQuery().
@@ -137,8 +137,8 @@ class CommentStorageController extends DatabaseStorageControllerNG {
         // has the lock, just move to the next integer.
         do {
           $thread = $prefix . comment_int_to_alphadecimal(++$n) . '/';
-        } while (!lock()->acquire("comment:{$comment->nid->target_id}:$thread"));
-        $this->threadLock = $thread;
+          $this->threadLock = lock()->acquire("comment:{$comment->nid->target_id}:$thread");
+        } while (!$this->threadLock);
       }
       if (empty($comment->created->value)) {
         $comment->created->value = REQUEST_TIME;
@@ -251,8 +251,8 @@ class CommentStorageController extends DatabaseStorageControllerNG {
    */
   protected function releaseThreadLock() {
     if ($this->threadLock) {
-      lock()->release($this->threadLock);
-      $this->threadLock = '';
+      $this->threadLock->release();
+      $this->threadLock = NULL;
     }
   }
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
index 38641f8..520da53 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
@@ -109,7 +109,7 @@ function testImportLock() {
     $this->assertNoText(t('There are no configuration changes.'));
 
     // Acquire a fake-lock on the import mechanism.
-    lock()->acquire('config_import');
+    $lock = lock()->acquire('config_import');
 
     // Attempt to import configuration and verify that an error message appears.
     $this->drupalPost(NULL, array(), t('Import all'));
@@ -117,7 +117,7 @@ function testImportLock() {
     $this->assertText(t('Another request may be synchronizing configuration already.'));
 
     // Release the lock, just to keep testing sane.
-    lock()->release('config_import');
+    $lock->release();
 
     // Verify site name has not changed.
     $this->assertNotEqual($new_site_name, config('system.site')->get('name'));
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 956eafd..2c3df4f 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -630,8 +630,8 @@ function image_style_deliver($style, $scheme) {
   // generation is in progress in another thread.
   $lock_name = 'image_style_deliver:' . $style->id() . ':' . drupal_hash_base64($image_uri);
   if (!file_exists($derivative_uri)) {
-    $lock_acquired = lock()->acquire($lock_name);
-    if (!$lock_acquired) {
+    $lock = lock()->acquire($lock_name);
+    if (!$lock) {
       // Tell client to retry again in 3 seconds. Currently no browsers are known
       // to support Retry-After.
       drupal_add_http_header('Status', '503 Service Unavailable');
@@ -645,8 +645,8 @@ function image_style_deliver($style, $scheme) {
   // acquiring the lock.
   $success = file_exists($derivative_uri) || image_style_create_derivative($style, $image_uri, $derivative_uri);
 
-  if (!empty($lock_acquired)) {
-    lock()->release($lock_name);
+  if (!empty($lock)) {
+    $lock->release($lock_name);
   }
 
   if ($success) {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Lock/LockFunctionalTest.php b/core/modules/system/lib/Drupal/system/Tests/Lock/LockFunctionalTest.php
index bf868db..73b0b8e 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Lock/LockFunctionalTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Lock/LockFunctionalTest.php
@@ -35,34 +35,37 @@ class LockFunctionalTest extends WebTestBase {
   public function testLockAcquire() {
     $lock_acquired = 'TRUE: Lock successfully acquired in system_test_lock_acquire()';
     $lock_not_acquired = 'FALSE: Lock not acquired in system_test_lock_acquire()';
-    $this->assertTrue(lock()->acquire('system_test_lock_acquire'), 'Lock acquired by this request.', 'Lock');
-    $this->assertTrue(lock()->acquire('system_test_lock_acquire'), 'Lock extended by this request.', 'Lock');
-    lock()->release('system_test_lock_acquire');
+    $lock = lock()->acquire('system_test_lock_acquire');
+    $this->assertTrue($lock, 'Lock acquired by this request.', 'Lock');
+    $this->assertTrue($lock->renew(), 'Lock extended by this request.', 'Lock');
+    $this->assertTrue($lock->release(), 'Lock released by this request.', 'Lock');
 
     // Cause another request to acquire the lock.
     $this->drupalGet('system-test/lock-acquire');
     $this->assertText($lock_acquired, 'Lock acquired by the other request.', 'Lock');
     // The other request has finished, thus it should have released its lock.
-    $this->assertTrue(lock()->acquire('system_test_lock_acquire'), 'Lock acquired by this request.', 'Lock');
+    $lock = lock()->acquire('system_test_lock_acquire');
+    $this->assertTrue($lock, 'Lock acquired by this request.', 'Lock');
     // This request holds the lock, so the other request cannot acquire it.
     $this->drupalGet('system-test/lock-acquire');
     $this->assertText($lock_not_acquired, 'Lock not acquired by the other request.', 'Lock');
-    lock()->release('system_test_lock_acquire');
+    $lock = $lock->release();
 
     // Try a very short timeout and lock breaking.
-    $this->assertTrue(lock()->acquire('system_test_lock_acquire', 0.5), 'Lock acquired by this request.', 'Lock');
+    $lock = lock()->acquire('system_test_lock_acquire', 0.5);
+    $this->assertTrue($lock, 'Lock acquired by this request.', 'Lock');
     sleep(1);
     // The other request should break our lock.
     $this->drupalGet('system-test/lock-acquire');
     $this->assertText($lock_acquired, 'Lock acquired by the other request, breaking our lock.', 'Lock');
     // We cannot renew it, since the other thread took it.
-    $this->assertFalse(lock()->acquire('system_test_lock_acquire'), 'Lock cannot be extended by this request.', 'Lock');
+    $this->assertFalse($lock->renew(), 'Lock cannot be extended by this request.', 'Lock');
 
-    // Check the shut-down function.
+    // Check the auto-release function.
     $lock_acquired_exit = 'TRUE: Lock successfully acquired in system_test_lock_exit()';
     $lock_not_acquired_exit = 'FALSE: Lock not acquired in system_test_lock_exit()';
     $this->drupalGet('system-test/lock-exit');
     $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');
+    $this->assertTrue(lock()->acquire('system_test_lock_acquire'), 'Lock acquired by this request after the other request exits.', 'Lock');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Lock/LockUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Lock/LockUnitTest.php
index b1666f3..5e553a0 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Lock/LockUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Lock/LockUnitTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Lock;
 
 use Drupal\Core\Lock\DatabaseLockBackend;
+use Drupal\Core\Lock\Lock;
 use Drupal\simpletest\DrupalUnitTestBase;
 
 /**
@@ -39,7 +40,7 @@ class LockUnitTest extends DrupalUnitTestBase {
 
   public function setUp() {
     parent::setUp();
-    $this->lock = new DatabaseLockBackend();
+    $this->backend = new DatabaseLockBackend();
     $this->installSchema('system', 'semaphore');
   }
 
@@ -47,43 +48,42 @@ class LockUnitTest extends DrupalUnitTestBase {
    * Tests backend release functionality.
    */
   public function testBackendLockRelease() {
-    $success = $this->lock->acquire('lock_a');
-    $this->assertTrue($success, 'Could acquire first lock.');
+    $lock_a = $this->backend->acquire('lock_a');
+    $this->assertTrue($lock_a, 'Could acquire first lock.');
 
     // This function is not part of the backend, but the default database
     // backend implement it, we can here use it safely.
-    $is_free = $this->lock->lockMayBeAvailable('lock_a');
+    $is_free = $this->backend->lockMayBeAvailable('lock_a');
     $this->assertFalse($is_free, 'First lock is unavailable.');
 
-    $this->lock->release('lock_a');
-    $is_free = $this->lock->lockMayBeAvailable('lock_a');
+    $lock_a->release();
+    $is_free = $this->backend->lockMayBeAvailable('lock_a');
     $this->assertTrue($is_free, 'First lock has been released.');
 
-    $success = $this->lock->acquire('lock_b');
-    $this->assertTrue($success, 'Could acquire second lock.');
+    $lock_b = $this->backend->acquire('lock_b');
+    $this->assertTrue($lock_b, 'Could acquire second lock.');
 
-    $success = $this->lock->acquire('lock_b');
+    $success = $lock_b->renew();
     $this->assertTrue($success, 'Could acquire second lock a second time within the same request.');
 
-    $this->lock->release('lock_b');
-  }
-
-  /**
-   * Tests backend release functionality.
-   */
-  public function testBackendLockReleaseAll() {
-    $success = $this->lock->acquire('lock_a');
-    $this->assertTrue($success, 'Could acquire first lock.');
+    $lock_b_2 = $this->backend->acquire('lock_b');
+    $this->assertFalse($lock_b_2, 'Could not acquire second lock a second time within the same request.');
 
-    $success = $this->lock->acquire('lock_b');
-    $this->assertTrue($success, 'Could acquire second lock.');
+    unset($lock_b);
+    $is_free = $this->backend->lockMayBeAvailable('lock_b');
+    $this->assertTrue($is_free, 'Second lock was released when it went out of scope.');
 
-    $this->lock->releaseAll();
+    $lock_c = $this->backend->acquire('lock_c');
+    $this->assertTrue($lock_c, 'Could acquire third lock.');
 
-    $is_free = $this->lock->lockMayBeAvailable('lock_a');
-    $this->assertTrue($is_free, 'First lock has been released.');
+    $lock_id = $lock_c->lockId();
+    $lock_c->autoRelease(FALSE);
+    unset($lock_c);
+    $this->assertTrue($is_free, 'Third lock was not released when it went out of scope.');
 
-    $is_free = $this->lock->lockMayBeAvailable('lock_b');
-    $this->assertTrue($is_free, 'Second lock has been released.');
+    $lock_c_2 = new Lock($this->backend, 'lock_c', $lock_id);
+    $lock_c_2->release();
+    $is_free = $this->backend->lockMayBeAvailable('lock_c');
+    $this->assertTrue($is_free, 'Third lock has been force-released.');
   }
 }
diff --git a/core/modules/system/tests/modules/system_test/system_test.module b/core/modules/system/tests/modules/system_test/system_test.module
index 4494299..bc57701 100644
--- a/core/modules/system/tests/modules/system_test/system_test.module
+++ b/core/modules/system/tests/modules/system_test/system_test.module
@@ -275,8 +275,9 @@ function system_test_system_info_alter(&$info, $file, $type) {
  * Try to acquire a named lock and report the outcome.
  */
 function system_test_lock_acquire() {
-  if (lock()->acquire('system_test_lock_acquire')) {
-    lock()->release('system_test_lock_acquire');
+  $lock = lock()->acquire('system_test_lock_acquire');
+  if ($lock) {
+    $lock->release('system_test_lock_acquire');
     return 'TRUE: Lock successfully acquired in system_test_lock_acquire()';
   }
   else {
diff --git a/core/modules/user/lib/Drupal/user/TempStore.php b/core/modules/user/lib/Drupal/user/TempStore.php
index c8a6dd1..5322d98 100644
--- a/core/modules/user/lib/Drupal/user/TempStore.php
+++ b/core/modules/user/lib/Drupal/user/TempStore.php
@@ -135,9 +135,9 @@ function setIfNotExists($key, $value) {
    *   The data to store.
    */
   function set($key, $value) {
-    if (!$this->lockBackend->acquire($key)) {
+    if (!($lock = $this->lockBackend->acquire($key))) {
       $this->lockBackend->wait($key);
-      if (!$this->lockBackend->acquire($key)) {
+      if (!($lock = $this->lockBackend->acquire($key))) {
         throw new TempStoreException(format_string("Couldn't acquire lock to update item %key in %collection temporary storage.", array(
           '%key' => $key,
           '%collection' => $this->storage->collection,
@@ -151,7 +151,6 @@ function set($key, $value) {
       'updated' => REQUEST_TIME,
     );
     $this->storage->setWithExpire($key, $value, $this->expire);
-    $this->lockBackend->release($key);
   }
 
   /**
@@ -181,9 +180,9 @@ function getMetadata($key) {
    *   The key of the data to delete.
    */
   function delete($key) {
-    if (!$this->lockBackend->acquire($key)) {
+    if (!($lock = $this->lockBackend->acquire($key))) {
       $this->lockBackend->wait($key);
-      if (!$this->lockBackend->acquire($key)) {
+      if (!($lock = $this->lockBackend->acquire($key))) {
         throw new TempStoreException(format_string("Couldn't acquire lock to delete item %key from %collection temporary storage.", array(
           '%key' => $key,
           '%collection' => $this->storage->collection,
@@ -191,7 +190,6 @@ function delete($key) {
       }
     }
     $this->storage->delete($key);
-    $this->lockBackend->release($key);
   }
 
 }
